Skip to content

Latest commit

 

History

History
executable file
·
336 lines (233 loc) · 9.17 KB

04-tutorial.md

File metadata and controls

executable file
·
336 lines (233 loc) · 9.17 KB
title
Tutorial

Creating Your First Bundle

Before we begin, you'll need to have Node.js installed so that you can use NPM. You'll also need to know how to access the command line on your machine.

The easiest way to use Rollup is via the Command Line Interface (or CLI). For now, we'll install it globally (later on we'll learn how to install it locally to your project so that your build process is portable, but don't worry about that yet). Type this into the command line:

npm install rollup --global
# or `npm i rollup -g` for short

You can now run the rollup command. Try it!

rollup

Because no arguments were passed, Rollup prints usage instructions. This is the same as running rollup --help, or rollup -h.

Let's create a simple project:

mkdir -p my-rollup-project/src
cd my-rollup-project

First, we need an entry point. Paste this into a new file called src/main.js:

// src/main.js
import foo from './foo.js';
export default function () {
  console.log(foo);
}

Then, let's create the foo.js module that our entry point imports:

// src/foo.js
export default 'hello world!';

Now we're ready to create a bundle:

rollup src/main.js -f cjs

The -f option (short for --format) specifies what kind of bundle we're creating — in this case, CommonJS (which will run in Node.js). Because we didn't specify an output file, it will be printed straight to stdout:

'use strict';

const foo = 'hello world!';

const main = function () {
  console.log(foo);
};

module.exports = main;

You can save the bundle as a file like so:

rollup src/main.js -o bundle.js -f cjs

(You could also do rollup src/main.js -f cjs > bundle.js, but as we'll see later, this is less flexible if you're generating sourcemaps.)

Try running the code:

node
> var myBundle = require('./bundle.js');
> myBundle();
'hello world!'

Congratulations! You've created your first bundle with Rollup.

Using Config Files

So far, so good, but as we start adding more options it becomes a bit of a nuisance to type out the command.

To save repeating ourselves, we can create a config file containing all the options we need. A config file is written in JavaScript and is more flexible than the raw CLI.

Create a file in the project root called rollup.config.js, and add the following code:

// rollup.config.js
export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  }
};

(Note that you can use CJS modules as well, to wit, module.exports = {/* config */})

To use the config file, we use the --config or -c flag:

rm bundle.js # so we can check the command works!
rollup -c

You can override any of the options in the config file with the equivalent command line options:

rollup -c -o bundle-2.js # `-o` is equivalent to `--file` (formerly "output")

Note: Rollup itself processes the config file, which is why we're able to use export default syntax – the code isn't being transpiled with Babel or anything similar, so you can only use ES2015 features that are supported in the version of Node.js that you're running.

You can, if you like, specify a different config file from the default rollup.config.js:

rollup --config rollup.config.dev.js
rollup --config rollup.config.prod.js

Using plugins

So far, we've created a simple bundle from an entry point and a module imported via a relative path. As you build more complex bundles, you'll often need more flexibility – importing modules installed with NPM, compiling code with Babel, working with JSON files and so on.

For that, we use plugins, which change the behaviour of Rollup at key points in the bundling process. A list of awesome plugins is maintained on the Rollup Awesome List.

For this tutorial, we'll use rollup-plugin-json, which allows Rollup to import data from a JSON file.

Create a file in the project root called package.json, and add the following content:

{
  "name": "rollup-tutorial",
  "version": "1.0.0",
  "scripts": {
    "build": "rollup -c"
  }
}

Install rollup-plugin-json as a development dependency:

npm install --save-dev rollup-plugin-json

(We're using --save-dev rather than --save because our code doesn't actually depend on the plugin when it runs – only when we're building the bundle.)

Update your src/main.js file so that it imports from your package.json instead of src/foo.js:

// src/main.js
import { version } from '../package.json';

export default function () {
  console.log('version ' + version);
}

Edit your rollup.config.js file to include the JSON plugin:

// rollup.config.js
import json from 'rollup-plugin-json';

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  },
  plugins: [ json() ]
};

Run Rollup with npm run build. The result should look like this:

'use strict';

const version = "1.0.0";

const main = function () {
  console.log('version ' + version);
};

module.exports = main;

Note: Only the data we actually need gets imported – name and devDependencies and other parts of package.json are ignored. That's tree-shaking in action!

Code Splitting

To use the code splitting feature, we got back to the original example and modify src/main.js to load src/foo.js dynamically instead of statically:

// src/main.js
export default function () {
  import('./foo.js').then(({ default: foo }) => console.log(foo));
}

Rollup will use the dynamic import to create a separate chunk that is only loaded on demand. In order for Rollup to know where to place the second chunk, instead of passing the --file option we set a folder to output to with the --dir option:

rollup src/main.js -f cjs -d dist

This will create a folder dist containing two files, main.js and chunk-[hash].js, where [hash] is a content based hash string. You can supply your own naming patterns by specifying the output.chunkFileNames and output.entryFileNames options.

You can still run your code as before with the same output, albeit a little slower as loading and parsing of ./foo.js will only commence once we call the exported function for the first time.

node -e "require('./dist/main.js')()"

If we do not use the --dir option, Rollup will again print the chunks to stdout, adding comments to highlight the chunk boundaries:

//→ main.js:
'use strict';

function main () {
  Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) => console.log(foo));
}

module.exports = main;

//→ chunk-b8774ea3.js:
'use strict';

var foo = 'hello world!';

exports.default = foo;

This is very useful if you want to load and parse expensive features only once they are used.

A different use for code-splitting is the ability to specify several entry points that share some dependencies. Again we extend our example to add a second entry point src/main2.js that statically imports src/foo.js just like we did in the original example:

// src/main2.js
import foo from './foo.js';
export default function () {
  console.log(foo);
}

If we supply both entry points to rollup, three chunks are created:

rollup src/main.js src/main2.js -f cjs

will output

//→ main.js:
'use strict';

function main () {
  Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) => console.log(foo));
}

module.exports = main;

//→ main2.js:
'use strict';

var foo_js = require('./chunk-b8774ea3.js');

function main2 () {
  console.log(foo_js.default);
}

module.exports = main2;

//→ chunk-b8774ea3.js:
'use strict';

var foo = 'hello world!';

exports.default = foo;

Notice how both entry points import the same shared chunk. Rollup will never duplicate code and instead create additional chunks to only ever load the bare minimum necessary. Again, passing the --dir option will write the files to disk.

You can build the same code for the browser via native ES modules, an AMD loader or SystemJS.

For example, with -f esm for native modules:

rollup src/main.js src/main2.js -f esm -d dist
<!doctype html>
<script type="module">
  import main2 from './dist/main2.js';
  main2();
</script>

Or alternatively, for SystemJS with -f system:

rollup src/main.js src/main2.js -f system -d dist

Install SystemJS via

npm install --save-dev systemjs

And then load either or both entry points in an HTML page as needed:

<!doctype html>
<script src="node_modules/systemjs/dist/system-production.js"></script>
<script>
  System.import('./dist/main2.js')
  .then(({ default: main }) => main());
</script>

See rollup-starter-code-splitting for an example on how to set up a web app that uses native ES modules on browsers that support them with a fallback to SystemJS if necessary.