split-file-webpack-plugin
TypeScript icon, indicating that this package has built-in type declarations

0.0.9 • Public • Published

split-file-webpack-plugin

This Webpack plugin splits individual input files into multiple output files based on comments in the input files. It creates source maps in the new files according to the source maps in the originals.

Why does this exist?

I wanted to write a Webpack loader that would use annotations on an input file to split up frontend and backend code into separate output files. This is impossible in Webpack's architecture, because loaders are assumed to be a string => string map, not string => string[]. This plugin was born to enable loaders to effectively be string => string[], as long as they use appropriate comment commands in their output Javascript.

How do I use it?

Easy! First:

npm install --save-dev split-file-webpack-plugin

Then add it to your Webpack config in the plugins array. For example:

var SplitFilePlugin = require("split-file-webpack-plugin");
module.exports = {
  entry: {
    app: "app.js"
  },
  output: {
    path: __dirname + "/public"
  },
  plugins: [new SplitFilePlugin()]
};

But be warned! This is very early alpha code. It's extremely unstable and liable to change at any time without warning.

How does it work?

START-NEW-FILE

The directives in the source files take the following form:

To write a section of an input file to a new file, named foo.js, include this comment to start your block:

/* @split-file-plugin:START-NEW-FILE:foo.js */

Include this comment to end your block:

/* @split-file-plugin:END-SECTION */

For example, if you had an input file that looked like this, called main.js:

// I will be in main.js
console.log("Hello main.js world");
/* @split-file-plugin:START-NEW-FILE:server.js */
// I will be in server.js
console.log("Hello server.js world");
/* @split-file-plugin:END-SECTION */

This plugin would output two files. One called main.js:

// I will be in main.js
console.log("Hello main.js world");

And one file called server.js:

// I will be in server.js
console.log("Hello server.js world");

Because START-NEW-FILE might want to produce something that isn't JS (like YAML), and Webpack assumes that all files are valid JS (and routinely is passing files through parsers), it's allowed to end a START-NEW-FILE line with an open block-quote /*. For example:

// I will be in main.js
console.log("Hello main.js world"); /*
/* @split-file-plugin:START-NEW-FILE:config.yaml */ /*
# I am a YAML file!
hello:
    world: 1
    foo: "bar"
/* @split-file-plugin:END-SECTION */

This outputs two files, main.js and config.yaml. They main.js looks like:

// I will be in main.js
console.log("Hello main.js world");

And config.yaml looks like:

# I am a YAML file!
hello:
  world: 1
  foo: "bar"

START-SPLIT

That's pretty much it, except for explaining the START-SPLIT command. Suppose that you have a common pre-amble that you want to include in a bunch of files, like the output of Webpack resolving a bunch of import statements. START-SPLIT will create a new file, but include everything in the source file that isn't directed to another file with a command. It's the original file plus the contents of the START-SPLIT section. For example, suppose main.js is:

import somelib;
/* @split-file-plugin:START-SPLIT:a.js */
console.log(somelib.foo());
/* @split-file-plugin:END-SECTION */
/* @split-file-plugin:START-SPLIT:b.js */
console.log(somelib.bar());
/* @split-file-plugin:END-SECTION */

This will output three files: main.js will contain just the common code, a.js will contain common code and its START-SPLIT section, and b.js will contain common code and its START-SPLIT section.

main.js:

import somelib;

a.js:

import somelib;
console.log(somelib.foo());

b.js:

import somelib;
console.log(somelib.bar());

There's one additional useful feature of START-SPLIT, which is that it allows you to specify custom export mappings for a given split. The motivating use case here is suppose you want to export an AWS Lambda as a split, you need to be able to set module.exports.handler = as some function at the end of your file. If you set that in the middle of your file, Webpack may swallow the export. So we put all the natural exports of your files in a variable exported, and allow you to write any exports you want after a -- in the START-SPLIT command. For example:

import somelib;
/* @split-file-plugin:START-SPLIT:a.js -- module.exports.handler = exported.a; */
export const a = 2;
/* @split-file-plugin:END-SECTION */

main.js:

import somelib;

a.js:

import somelib;
exported.a = 2;
module.exports.handler = exported.a;

For a good example of the use of this feature of START-SPLIT, see the babel-plugin-serverside-annotation project.

NO-SPLIT

This cuts off a section from any splits, leaving it only available in the root js file. For example, suppose main.js is:

import somelib;
/* @split-file-plugin:START-SPLIT:a.js */
console.log(somelib.foo());
/* @split-file-plugin:END-SECTION */
/* @split-file-plugin:NO-SPLIT */
console.log(somelib.bar());
/* @split-file-plugin:END-SECTION */

This will output two files: main.js will contain just the common code, a.js will contain common code and its START-SPLIT section, excluding the NO-SPLIT section.

main.js:

import somelib;
console.log(somelib.bar());

a.js:

import somelib;
console.log(somelib.foo());

Administrivia

This is distributed under a GPLv3 license.

Readme

Keywords

Package Sidebar

Install

npm i split-file-webpack-plugin

Weekly Downloads

9

Version

0.0.9

License

GPLv3

Unpacked Size

86 kB

Total Files

7

Last publish

Collaborators

  • keenon