Skip to content

Commit

Permalink
Merge pull request parcel-bundler#7 from parcel-bundler/master
Browse files Browse the repository at this point in the history
a
  • Loading branch information
Jasper De Moor authored Dec 12, 2017
2 parents 392bbc9 + b7b2991 commit e616cc2
Show file tree
Hide file tree
Showing 27 changed files with 364 additions and 122 deletions.
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ Search open/closed issues before submitting since someone might have asked the s
| Node |
| npm/Yarn |
| Operating System |

<!-- Love parcel? Please consider supporting our collective:
👉 https://opencollective.com/parcel/donate -->
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ coverage
dist
lib
!test/**/node_modules
.vscode/
.vscode/
.idea/
38 changes: 38 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,41 @@ yarn test
[git]: https://git-scm.com/
[node]: https://nodejs.org/
[yarn]: https://yarnpkg.com/


## Financial contributions

We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/parcel).
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.


## Credits


### Contributors

Thank you to all the people who have already contributed to parcel!
<a href="graphs/contributors"><img src="https://opencollective.com/parcel/contributors.svg?width=890" /></a>


### Backers

Thank you to all our backers! [[Become a backer](https://opencollective.com/parcel#backer)]

<a href="https://opencollective.com/parcel#backers" target="_blank"><img src="https://opencollective.com/parcel/backers.svg?width=890"></a>


### Sponsors

Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/parcel#sponsor))

<a href="https://opencollective.com/parcel/sponsor/0/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/1/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/2/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/3/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/4/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/5/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/6/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/7/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/8/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/9/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/9/avatar.svg"></a>
56 changes: 45 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
</a>
</p>

[![Backers on Open Collective](https://opencollective.com/parcel/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/parcel/sponsors/badge.svg)](#sponsors)
[![Travis CI Build Status](https://travis-ci.org/parcel-bundler/parcel.svg?branch=master)](https://travis-ci.org/parcel-bundler/parcel)
[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/nr7d6qjxj3wwsw6n?svg=true)](https://ci.appveyor.com/project/devongovett/parcel)
[![David Dependancy Status](https://david-dm.org/parcel-bundler/parcel.svg)](https://david-dm.org/parcel-bundler/parcel)
Expand All @@ -14,20 +15,24 @@

## Features

- 🚀 **Blazing fast** bundle times - multicore compilation, and a filesystem cache for fast rebuilds even after a restart.
- 📦 Out of the box support for JS, CSS, HTML, file assets, and more - **no plugins to install**.
- 🐠 **Automatically transforms modules** using Babel, PostCSS, and PostHTML when needed - even `node_modules`.
- ✂️ Zero configuration **code splitting** using dynamic `import()` statements.
- 🔥 Built in support for **hot module replacement**
- 🚨 Friendly error logging experience - syntax highlighted code frames help pinpoint the problem.
* 🚀 **Blazing fast** bundle times - multicore compilation, and a filesystem cache for fast rebuilds even after a restart.
* 📦 Out of the box support for JS, CSS, HTML, file assets, and more - **no plugins to install**.
* 🐠 **Automatically transforms modules** using Babel, PostCSS, and PostHTML when needed - even `node_modules`.
* ✂️ Zero configuration **code splitting** using dynamic `import()` statements.
* 🔥 Built in support for **hot module replacement**
* 🚨 Friendly error logging experience - syntax highlighted code frames help pinpoint the problem.

## Getting started

1. Install with npm or yarn:
1. Install with yarn:

```shell
yarn global add parcel-bundler
```
or with npm:
```shell
npm install -g parcel-bundler
```

2. Parcel can take any type of file as an entry point, but an HTML or JavaScript file is a good place to start. If you link your main JavaScript file in the HTML using a relative path, Parcel will also process it for you, and replace the reference with a URL to the output file.

Expand Down Expand Up @@ -74,7 +79,7 @@ Finally, existing bundlers are built around string loaders/transforms, where the

`parcel` transforms a tree of assets to a tree of bundles. Many other bundlers are fundamentally based around JavaScript assets, with other formats tacked on - for example, by default inlined as strings into JS files. `parcel` is file-type agnostic - it will work with any type of assets the way you'd expect, with no configuration.

`parcel` takes as input a single entry asset, which could be any type: a JS file, HTML, CSS, image, etc. There are various asset types defined in `parcel` which know how to handle specific file types. The assets are parsed, their dependencies are extracted, and they are transformed to their final compiled form. This creates a tree of assets.
`parcel` takes as input a single entry asset, which could be any type: a JS file, HTML, CSS, image, etc. There are various asset types defined in `parcel` which know how to handle specific file types. The assets are parsed, their dependencies are extracted, and they are transformed to their final compiled form. This creates a tree of assets.

Once the asset tree has been constructed, the assets are placed into a bundle tree. A bundle is created for the entry asset, and child bundles are created for dynamic imports, which cause code splitting to occur. Child bundles are also created when assets of a different type are imported, for example if you imported a CSS file from JavaScript, it would be placed into a sibling bundle to the corresponding JavaScript. If an asset is required in more than one bundle, it is hoisted up to the nearest common ancestor in the bundle tree so it is not included more than once.

Expand All @@ -84,10 +89,39 @@ After the bundle tree is constructed, each bundle is written to a file by a pack

All feedback and suggestions are welcome!

- 💬 Chat: Join us on [slack](https://slack.parceljs.org/).
- 📣 Stay up to date on new features and announcements on [@parceljs](https://twitter.com/parceljs).
* 💬 Chat: Join us on [slack](https://slack.parceljs.org/).
* 📣 Stay up to date on new features and announcements on [@parceljs](https://twitter.com/parceljs).

## Contributors

This project exists thanks to all the people who contribute. [[Contribute]](CONTRIBUTING.md).
<a href="graphs/contributors"><img src="https://opencollective.com/parcel/contributors.svg?width=890" /></a>


## Backers

Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/parcel#backer)]

<a href="https://opencollective.com/parcel#backers" target="_blank"><img src="https://opencollective.com/parcel/backers.svg?width=890"></a>


## Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/parcel#sponsor)]

<a href="https://opencollective.com/parcel/sponsor/0/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/1/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/2/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/3/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/4/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/5/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/6/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/7/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/8/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/parcel/sponsor/9/website" target="_blank"><img src="https://opencollective.com/parcel/sponsor/9/avatar.svg"></a>



## License

MIT

4 changes: 2 additions & 2 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ if (!args[2] || !program.commands.some(c => c.name() === args[2])) {

program.parse(args);

function bundle(main, command) {
async function bundle(main, command) {
// Require bundler here so the help command is fast
const Bundler = require('../');

Expand All @@ -94,7 +94,7 @@ function bundle(main, command) {
const bundler = new Bundler(main, command);

if (command.name() === 'serve') {
const server = bundler.serve(command.port || 1234);
const server = await bundler.serve(command.port || 1234);
if (command.open) {
require('opn')(`http://localhost:${server.address().port}`);
}
Expand Down
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "parcel-bundler",
"version": "1.1.0",
"version": "1.2.0",
"main": "index.js",
"license": "MIT",
"repository": {
Expand All @@ -11,14 +11,14 @@
"babel-core": "^6.25.0",
"babel-generator": "^6.25.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-to-estree": "^0.0.3",
"babylon": "^6.17.4",
"babylon-walk": "^1.0.2",
"browser-resolve": "^1.11.2",
"chalk": "^2.1.0",
"chokidar": "^1.7.0",
"commander": "^2.11.0",
"cssnano": "^3.10.0",
"get-port": "^3.2.0",
"glob": "^7.1.2",
"htmlnano": "^0.1.6",
"is-url": "^1.2.2",
Expand All @@ -35,14 +35,15 @@
"resolve": "^1.4.0",
"serve-static": "^1.12.4",
"strip-json-comments": "^2.0.1",
"uglify-js": "^3.0.28",
"uglify-es": "^3.2.1",
"v8-compile-cache": "^1.1.0",
"worker-farm": "^1.4.1",
"ws": "^3.3.2"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"coffeescript": "^2.0.3",
"cross-env": "^5.1.1",
"husky": "^0.14.3",
"less": "^2.7.2",
Expand All @@ -64,7 +65,8 @@
"format": "prettier --write './{src,bin,test}/**/*.{js,json,md}'",
"build": "babel src -d lib",
"prepublish": "yarn build",
"precommit": "lint-staged"
"precommit": "lint-staged",
"postinstall": "node -e \"console.log('\\u001b[35m\\u001b[1mLove Parcel? You can now donate to our open collective:\\u001b[22m\\u001b[39m\\n > \\u001b[34mhttps://opencollective.com/parcel/donate\\u001b[0m')\""
},
"bin": {
"parcel": "bin/cli.js"
Expand All @@ -73,6 +75,13 @@
"node": ">= 6.0.0"
},
"lint-staged": {
"*.{js,json,md}": ["prettier --write", "git add"]
"*.{js,json,md}": [
"prettier --write",
"git add"
]
},
"collective": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
}
21 changes: 12 additions & 9 deletions src/Bundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const {EventEmitter} = require('events');
const Logger = require('./Logger');
const PackagerRegistry = require('./packagers');
const localRequire = require('./utils/localRequire');
const customErrors = require('./utils/customErrors');
const config = require('./utils/config');

/**
* The Bundler is the main entry point. It resolves and loads assets,
Expand Down Expand Up @@ -40,8 +42,6 @@ class Bundler extends EventEmitter {
this.errored = false;
this.buildQueue = new Set();
this.rebuildTimeout = null;

this.loadPlugins();
}

normalizeOptions(options) {
Expand Down Expand Up @@ -87,9 +87,13 @@ class Bundler extends EventEmitter {
this.packagers.add(type, packager);
}

loadPlugins() {
async loadPlugins() {
let pkg = await config.load(this.mainFile, ['package.json']);
if (!pkg) {
return;
}

try {
let pkg = localRequire('./package.json', this.mainFile);
let deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
for (let dep in deps) {
if (dep.startsWith('parcel-plugin-')) {
Expand Down Expand Up @@ -168,6 +172,8 @@ class Bundler extends EventEmitter {
return;
}

await this.loadPlugins();

this.options.extensions = Object.assign({}, this.parser.extensions);
this.farm = WorkerFarm.getShared(this.options);

Expand Down Expand Up @@ -452,12 +458,9 @@ class Bundler extends EventEmitter {
return Server.middleware(this);
}

serve(port = 1234) {
this.logger.persistent(
'Server running at ' + this.logger.chalk.cyan(`http://localhost:${port}`)
);
async serve(port = 1234) {
this.bundle();
return Server.serve(this, port);
return await Server.serve(this, port);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Parser {
this.registerExtension('mjs', './assets/JSAsset');
this.registerExtension('ts', './assets/TypeScriptAsset');
this.registerExtension('tsx', './assets/TypeScriptAsset');
this.registerExtension('coffee', './assets/CoffeeScriptAsset');
this.registerExtension('json', './assets/JSONAsset');
this.registerExtension('yaml', './assets/YAMLAsset');
this.registerExtension('yml', './assets/YAMLAsset');
Expand Down
27 changes: 25 additions & 2 deletions src/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const http = require('http');
const path = require('path');
const url = require('url');
const serveStatic = require('serve-static');
const getPort = require('get-port');
const serverErrors = require('./utils/customErrors').serverErrors;

function middleware(bundler) {
const serve = serveStatic(bundler.options.outDir, {index: false});
Expand Down Expand Up @@ -54,8 +56,29 @@ function middleware(bundler) {
};
}

function serve(bundler, port) {
return http.createServer(middleware(bundler)).listen(port);
async function serve(bundler, port) {
let freePort = await getPort({port});
let server = http.createServer(middleware(bundler)).listen(freePort);

server.on('error', err => {
bundler.logger.error(new Error(serverErrors(err, server.address().port)));
});

server.once('listening', connection => {
let addon =
server.address().port !== port
? `- ${bundler.logger.chalk.red(
`configured port ${port} could not be used.`
)}`
: '';
bundler.logger.persistent(
`Server running at ${bundler.logger.chalk.cyan(
`http://localhost:${server.address().port}`
)} ${addon}\n`
);
});

return server;
}

exports.middleware = middleware;
Expand Down
16 changes: 16 additions & 0 deletions src/assets/CoffeeScriptAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const JSAsset = require('./JSAsset');
const config = require('../utils/config');
const localRequire = require('../utils/localRequire');

class CoffeeScriptAsset extends JSAsset {
async parse(code) {
// require coffeescript, installed locally in the app
let coffee = localRequire('coffeescript', this.name);

// Transpile Module using CoffeeScript and parse result as ast format through babylon
this.contents = coffee.compile(code, {});
return await super.parse(this.contents);
}
}

module.exports = CoffeeScriptAsset;
5 changes: 4 additions & 1 deletion src/builtins/bundle-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ function loadBundle(bundle) {
}

var type = bundle.match(/\.(.+)$/)[1].toLowerCase();
return bundles[bundle] = bundleLoaders[type](getBundleURL() + bundle);
var bundleLoader = bundleLoaders[type];
if (bundleLoader) {
return bundles[bundle] = bundleLoader(getBundleURL() + bundle);
}
}

function loadJSBundle(bundle) {
Expand Down
Loading

0 comments on commit e616cc2

Please sign in to comment.