Skip to content

Commit

Permalink
feat: add 'only'/'exclude' options
Browse files Browse the repository at this point in the history
closes #10
  • Loading branch information
mastilver committed Jul 2, 2017
1 parent 30dd7b6 commit 713d74f
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"webpack": "2.x"
},
"devDependencies": {
"ava": "^0.19.1",
"ava": "^0.20.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
Expand Down
15 changes: 15 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,21 @@ Values: `development`, `production`

Determine if it should load the development or the production version of modules

#### options.only

Type: `Array<string>`
Default: `null`

List the only modules that should be served by the cdn


#### options.exclude

Type: `Array<string>`
Default: `[]`

List the modules that will always be bundled (not be served by the cdn)


## Related

Expand Down
14 changes: 13 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ try {
}

export default class ModulesCdnWebpackPlugin {
constructor({disable = false, env} = {}) {
constructor({disable = false, env, exclude, only} = {}) {
if (exclude && only) {
throw new Error('You can\'t use \'exclude\' and \'only\' at the same time');
}

this.disable = disable;
this.env = env || process.env.NODE_ENV || 'development';
this.urls = {};
this.exclude = exclude || [];
this.only = only || null;
}

apply(compiler) {
Expand Down Expand Up @@ -56,6 +62,12 @@ export default class ModulesCdnWebpackPlugin {
}

addModule(contextPath, modulePath, {env}) {
const isModuleExcluded = this.exclude.includes(modulePath) ||
(this.only && !this.only.includes(modulePath));
if (isModuleExcluded) {
return false;
}

const {version, peerDependencies} = readPkg(resolvePkg(modulePath, {cwd: contextPath}));

const cdnConfig = moduleToCdn(modulePath, version, {env});
Expand Down
103 changes: 100 additions & 3 deletions test/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('basic', async t => {
const output = await fs.readFile(path.resolve(__dirname, './fixtures/output/basic/app.js'));

// NOTE: not inside t.false to prevent ava to display whole file in console
const doesIncludeReact = includes(output, 'PureComponent');
const doesIncludeReact = includes(output, 'THIS IS REACT!');
t.false(doesIncludeReact);

const doesRequireReact = includes(output, 'module.exports = React');
Expand Down Expand Up @@ -74,7 +74,7 @@ test('using production version', async t => {
const output = await fs.readFile(path.resolve(__dirname, './fixtures/output/env-prod/app.js'));

// NOTE: not inside t.false to prevent ava to display whole file in console
const doesIncludeReact = includes(output, 'PureComponent');
const doesIncludeReact = includes(output, 'THIS IS REACT!');
t.false(doesIncludeReact);
});

Expand Down Expand Up @@ -108,7 +108,7 @@ test.serial('with NODE_ENV=production', async t => {
const output = await fs.readFile(path.resolve(__dirname, './fixtures/output/node-env-prod/app.js'));

// NOTE: not inside t.false to prevent ava to display whole file in console
const doesIncludeReact = includes(output, 'PureComponent');
const doesIncludeReact = includes(output, 'THIS IS REACT!');
t.false(doesIncludeReact);

delete process.env.NODE_ENV;
Expand Down Expand Up @@ -192,3 +192,100 @@ test('load module without export', async t => {
t.true(includes(files, 'app.js'));
t.true(includes(files, 'https://unpkg.com/[email protected]/dist/polyfill.js'));
});

test('exclude some modules', async t => {
await cleanDir(path.resolve(__dirname, './fixtures/output/exclude'));

const stats = await runWebpack({
context: path.resolve(__dirname, './fixtures/single'),

output: {
publicPath: '',
path: path.resolve(__dirname, './fixtures/output/exclude')
},

entry: {
app: './index.js'
},

plugins: [
new ModulesCdnWebpackPlugin({
exclude: ['react']
})
]
});

const files = stats.compilation.chunks.reduce((files, x) => files.concat(x.files), []);

t.true(includes(files, 'app.js'));
t.false(includes(files, 'https://unpkg.com/[email protected]/dist/react.js'));

const output = await fs.readFile(path.resolve(__dirname, './fixtures/output/exclude/app.js'));

// NOTE: not inside t.true to prevent ava to display whole file in console
const doesIncludeReact = includes(output, 'THIS IS REACT!');
t.true(doesIncludeReact);
});

test('only include some modules', async t => {
await cleanDir(path.resolve(__dirname, './fixtures/output/only'));

const stats = await runWebpack({
context: path.resolve(__dirname, './fixtures/multiple'),

output: {
publicPath: '',
path: path.resolve(__dirname, './fixtures/output/only')
},

entry: {
app: './index.js'
},

plugins: [
new ModulesCdnWebpackPlugin({
only: ['react']
})
]
});

const files = stats.compilation.chunks.reduce((files, x) => files.concat(x.files), []);

t.true(includes(files, 'app.js'));
t.true(includes(files, 'https://unpkg.com/[email protected]/dist/react.js'));
t.false(includes(files, 'https://unpkg.com/[email protected]/dist/polyfill.js'));
t.false(includes(files, 'https://unpkg.com/[email protected]/dist/react-dom.js'));

const output = await fs.readFile(path.resolve(__dirname, './fixtures/output/only/app.js'));

// NOTE: not inside t.true to prevent ava to display whole file in console
const doesIncludeReactDom = includes(output, 'THIS IS REACT DOM!');
t.true(doesIncludeReactDom);

const doesIncludeBabelPolyfill = includes(output, 'THIS IS BABEL POLYFILL!');
t.true(doesIncludeBabelPolyfill);
});

test('errors when using \'only\' and \'exclude\' together', async t => {
await cleanDir(path.resolve(__dirname, './fixtures/output/error'));

t.throws(() => runWebpack({
context: path.resolve(__dirname, './fixtures/single'),

output: {
publicPath: '',
path: path.resolve(__dirname, './fixtures/output/error')
},

entry: {
app: './index.js'
},

plugins: [
new ModulesCdnWebpackPlugin({
exclude: ['react'],
only: ['react']
})
]
}), /You can't use 'exclude' and 'only' at the same time/);
});
4 changes: 4 additions & 0 deletions test/fixtures/multiple/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'babel-polyfill';

import React from 'react';
import ReactDom from 'react-dom';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions test/fixtures/multiple/node_modules/babel-polyfill/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/fixtures/multiple/node_modules/react-dom/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions test/fixtures/multiple/node_modules/react-dom/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions test/fixtures/multiple/node_modules/react/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/fixtures/multiple/node_modules/react/react.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 713d74f

Please sign in to comment.