Skip to content

Commit 02fe150

Browse files
committed
initial commit
1 parent 72fedaa commit 02fe150

20 files changed

Lines changed: 1691 additions & 199 deletions

README.md

Lines changed: 15 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,22 @@
1-
<p align="center">
2-
<img src="https://i.imgur.com/MlrAQjl.jpg" width="1000" alt="worker-plugin">
3-
</p>
4-
<h1 align="center">👩‍🏭 worker-plugin</h1>
5-
<p align="center">Automatically bundle & compile Web Workers within Webpack.</p>
1+
# Optimize Plugin for Webpack
62

3+
Optimize your code for modern browsers while still supporting the other 10%, increasing your build performance, reducing bundle size and improving output quality.
74

8-
### Features
9-
10-
Automatically compiles modules loaded in Web Workers:
11-
12-
```js
13-
const worker = new Worker('./foo.js', { type: 'module' });
14-
^^^^^^^^^^
15-
gets bundled using webpack
16-
```
17-
18-
The best part? That worker constructor works just fine without bundling turned on too.
19-
20-
Workers created from Blob & data URLs or without the `{ type:'module' }` option are left unchanged.
21-
22-
## Installation
23-
24-
```sh
25-
npm install -D worker-plugin
26-
```
27-
28-
Then drop it into your **webpack.config.js:**
29-
30-
```diff
31-
+ const WorkerPlugin = require('worker-plugin');
32-
33-
module.exports = {
34-
<...>
35-
plugins: [
36-
+ new WorkerPlugin()
37-
]
38-
<...>
39-
}
40-
```
41-
42-
## Usage
43-
44-
**worker.js**: _(our worker module)_
45-
46-
```js
47-
// This is a module worker, so we can use imports (in the browser too!)
48-
import { calculatePi } from './some-other-module';
49-
50-
addEventListener('message', event => {
51-
postMessage(calculatePi(event.data));
52-
});
53-
```
54-
55-
**main.js**: _(our demo, on the main thread)_
5+
Put simply: it compiles code faster, better and smaller.
566

57-
```js
58-
const piWorker = new Worker('./worker.js', { type: 'module' });
59-
piWorker.onmessage = event => {
60-
console.log('pi: ' + event.data);
61-
};
62-
piWorker.postMessage(42);
63-
```
64-
65-
## Options
66-
67-
In most cases, no options are necessary to use WorkerPlugin.
68-
69-
### `globalObject`
70-
71-
WorkerPlugin will warn you if your Webpack configuration has `output.globalObject` set to `window`, since doing so breaks Hot Module Replacement in web workers.
72-
73-
If you're not using HMR and want to disable this warning, pass `globalObject:false`:
74-
75-
```js
76-
new WorkerPlugin({
77-
// disable warnings about "window" breaking HMR:
78-
globalObject: false
79-
})
80-
```
81-
82-
To configure the value of `output.globalObject` for WorkerPlugin's internal Webpack Compiler, set `globalObject` to any String:
83-
84-
```js
85-
new WorkerPlugin({
86-
// use "self" as the global object when receiving hot updates.
87-
globalObject: 'self' // <-- this is the default value
88-
})
89-
```
90-
91-
### `plugins`
92-
93-
By default, `WorkerPlugin` doesn't run any of your configured Webpack plugins when bundling worker code - this avoids running things like `html-webpack-plugin` twice. For cases where it's necessary to apply a plugin to Worker code, use the `plugins` option.
7+
### Features
948

95-
Here you can specify the names of plugins to "copy" from your existing Webpack configuration, or provide specific plugins to apply only to worker code:
9+
- Much faster than your current Webpack setup
10+
- Transparently optimizes all of your code
11+
- Automatically optimizes all of your dependencies
12+
- Compiles bundles for modern browsers (90%) and legacy browsers (10%)
13+
- Removes unnecessary polyfills, even when inlined into dependencies
14+
- Compiles a highly-optimized dedicated polyfills bundle
9615

9716
```js
98-
module.exports = {
99-
<...>
100-
plugins: [
101-
// an example of a plugin already being used:
102-
new SomeExistingPlugin({ <...> }),
103-
104-
new WorkerPlugin({
105-
plugins: [
106-
// A string here will copy the named plugin from your configuration:
107-
'SomeExistingPlugin',
108-
109-
// Or you can specify a plugin directly, only applied to Worker code:
110-
new SomePluginToApplyOnlyToWorkers({ <...> })
111-
]
112-
})
113-
]
114-
<...>
115-
}
17+
plugins: [
18+
new OptimizePlugin({
19+
// options
20+
})
21+
]
11622
```
117-
118-
## License
119-
120-
Apache-2.0

package.json

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"build": "microbundle --target node --format cjs --no-compress src/*.js",
99
"prepack": "npm run build",
1010
"dev": "jest --verbose --watchAll",
11-
"test": "npm run build && jest --verbose",
11+
"test": "jest --verbose",
1212
"release": "npm t && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
1313
},
1414
"babel": {
@@ -21,23 +21,31 @@
2121
}
2222
},
2323
"eslintConfig": {
24-
"extends": "eslint-config-standard",
24+
"extends": [
25+
"standard",
26+
"plugin:jest/recommended"
27+
],
28+
"parserOptions": {
29+
"sourceType": "module",
30+
"ecmaVersion": 2020
31+
},
2532
"env": {
2633
"browser": true,
2734
"jest": true
2835
},
2936
"rules": {
3037
"indent": [
31-
"error",
38+
2,
3239
2
3340
],
3441
"semi": [
35-
"error",
42+
2,
3643
"always"
3744
]
3845
}
3946
},
4047
"jest": {
48+
"testEnvironment": "node",
4149
"watchPathIgnorePatterns": [
4250
"<rootDir>/node_modules/",
4351
"<rootDir>/test/fixtures/"
@@ -65,26 +73,32 @@
6573
"ast-types": "^0.13.2",
6674
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
6775
"clean-webpack-plugin": "^1.0.0",
68-
"eslint": "^5.9.0",
69-
"eslint-config-standard": "^12.0.0",
76+
"eslint": "^6.8.0",
77+
"eslint-config-standard": "^14.1.0",
7078
"eslint-plugin-import": "^2.14.0",
71-
"eslint-plugin-node": "^8.0.0",
79+
"eslint-plugin-jest": "^23.6.0",
80+
"eslint-plugin-node": "^11.0.0",
7281
"eslint-plugin-promise": "^4.0.1",
73-
"eslint-plugin-standard": "^4.0.0",
74-
"jest": "^23.6.0",
82+
"eslint-plugin-standard": "^4.0.1",
83+
"jest": "^25.1.0",
7584
"memory-fs": "^0.4.1",
7685
"microbundle": "^0.12.0-next.8",
86+
"preact": "^10.2.1",
87+
"sucrase": "^3.12.1",
7788
"terser-webpack-plugin": "^1.1.0",
89+
"ts-loader": "^6.2.1",
7890
"webpack": "^4.26.1"
7991
},
8092
"dependencies": {
81-
"@babel/core": "^7.8.3",
93+
"@babel/core": "^7.8.4",
8294
"@babel/preset-modules": "^0.1.2",
8395
"@rollup/plugin-commonjs": "^11.0.1",
8496
"@rollup/plugin-node-resolve": "^7.0.0",
8597
"core-js": "^3.6.4",
98+
"gzip-size": "^5.1.1",
8699
"jest-worker": "^25.1.0",
87100
"magic-string": "^0.25.6",
101+
"regenerator-runtime": "^0.13.3",
88102
"rollup": "^1.29.1",
89103
"terser": "^4.6.3",
90104
"webpack-sources": "^1.4.3"

src/index.js

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
* the License.
1515
*/
1616

17+
import path from 'path';
1718
import util from 'util';
1819
import { gzip } from 'zlib';
1920
import { promises as fs } from 'fs';
2021
import * as webpack from 'webpack';
2122
import { SourceMapSource, RawSource } from 'webpack-sources';
2223
import { rollup } from 'rollup';
2324
import commonjsPlugin from '@rollup/plugin-commonjs';
24-
// import nodeResolvePlugin from '@rollup/plugin-node-resolve';
25+
import nodeResolvePlugin from '@rollup/plugin-node-resolve';
2526
import rollupPluginTerserSimple from './lib/rollup-plugin-terser-simple';
2627
import rollupPluginStripComments from './lib/rollup-plugin-strip-comments';
2728
import { getCorejsVersion, createPerformanceTimings } from './lib/util';
@@ -69,7 +70,7 @@ export default class OptimizePlugin {
6970
*/
7071
constructor (options) {
7172
this.options = Object.assign({}, options || {});
72-
for (let i in DEFAULT_OPTIONS) {
73+
for (const i in DEFAULT_OPTIONS) {
7374
if (this.options[i] == null) this.options[i] = DEFAULT_OPTIONS[i];
7475
}
7576

@@ -218,28 +219,28 @@ export default class OptimizePlugin {
218219
* @todo Write cached polyfills chunk to disk
219220
*/
220221
async generatePolyfillsChunk (polyfills, cwd, timings) {
221-
const ENTRY = `\0entry`;
222+
const ENTRY = '\0entry';
222223

223224
const entryContent = polyfills.reduce((str, p) => `${str}\nimport "${p}";`, '');
224225

225226
const COREJS = require.resolve('core-js/package.json').replace('package.json', '');
226227
const isCoreJsPath = /(?:^|\/)core-js\/(.+)$/;
227-
const nonCoreJsPolyfills = polyfills.filter(p => !/core-js/.test(p));
228+
const nonCoreJsPolyfills = polyfills.filter(p => !/(core-js|regenerator-runtime)/.test(p));
229+
230+
if (timings && nonCoreJsPolyfills.length) {
231+
console.log(` Bundling ${nonCoreJsPolyfills.length} unrecognized polyfills.`);
232+
}
228233

229234
const polyfillsBundle = await rollup({
230235
cache: this.rollupCache,
231236
context: 'window',
232-
// inlineDynamicImports: true,
233-
perf: true,
237+
perf: !!timings,
234238
input: ENTRY,
235239
treeshake: {
236240
propertyReadSideEffects: false,
237241
tryCatchDeoptimization: false,
238242
unknownGlobalSideEffects: false
239243
},
240-
// external: [
241-
// 'core-js'
242-
// ],
243244
plugins: [
244245
{
245246
name: 'entry',
@@ -249,9 +250,11 @@ export default class OptimizePlugin {
249250
{
250251
name: 'core-js',
251252
resolveId (id) {
253+
if (/^regenerator-runtime(\/|$)/.test(id)) {
254+
return require.resolve('regenerator-runtime/runtime');
255+
}
252256
const m = id.match(isCoreJsPath);
253257
if (m && !/\.js$/.test(id)) {
254-
// console.log(COREJS + m[1] + '.js');
255258
return COREJS + m[1] + '.js';
256259
}
257260
return null;
@@ -266,20 +269,33 @@ export default class OptimizePlugin {
266269
},
267270
// coreJsPlugin(),
268271
commonjsPlugin({
269-
sourceMap: false,
270-
ignoreGlobal: true
272+
// ignoreGlobal: true,
273+
sourceMap: false
271274
}),
272-
// nodeResolvePlugin({
273-
// dedupe: polyfills,
274-
// preferBuiltins: false,
275-
// rootDir: cwd
276-
// }),
277-
nonCoreJsPolyfills.length ? nodeResolvePlugin({
278-
dedupe: polyfills,
279-
preferBuiltins: false,
280-
rootDir: cwd,
281-
only: nonCoreJsPolyfills
282-
}) : null,
275+
nonCoreJsPolyfills.length && nodeResolvePlugin({
276+
dedupe: nonCoreJsPolyfills,
277+
only: nonCoreJsPolyfills,
278+
preferBuiltins: false
279+
// rootDir: cwd,
280+
// customResolveOptions: {
281+
// paths: [
282+
// path.resolve(__dirname, '../node_modules')
283+
// ]
284+
// }
285+
}),
286+
// {
287+
// name: 'babel',
288+
// renderChunk (source) {
289+
// return require('@babel/core').transformAsync(source, {
290+
// sourceMaps: false,
291+
// minified: true,
292+
// shouldPrintComment: () => false,
293+
// presets: [
294+
// require('../../babel-preset-optimize')
295+
// ]
296+
// });
297+
// }
298+
// },
283299
this.options.minify ? (
284300
rollupPluginTerserSimple()
285301
) : (
@@ -300,15 +316,17 @@ export default class OptimizePlugin {
300316
});
301317
const output = result.output[0];
302318

303-
const times = polyfillsBundle.getTimings();
304-
// console.log(times);
305-
const add = (name, timing) => {
306-
const t = times[timing];
307-
if (t) timings.push({ depth: 2, name, duration: t[0] });
308-
};
309-
add('parse', '## parse modules');
310-
add('node-resolve', '- plugin 2 (node-resolve) - resolveId (async)');
311-
add('generate', '# GENERATE');
319+
// If verbose logging is enabled, bubble up some useful Rollup time information
320+
if (timings) {
321+
const times = polyfillsBundle.getTimings();
322+
const add = (name, timing) => {
323+
const t = times[timing];
324+
if (t) timings.push({ depth: 2, name, duration: t[0] });
325+
};
326+
add('parse', '## parse modules');
327+
add('node-resolve', '- plugin 2 (node-resolve) - resolveId (async)');
328+
add('generate', '# GENERATE');
329+
}
312330

313331
return output;
314332
}
@@ -356,11 +374,18 @@ export default class OptimizePlugin {
356374
}, '');
357375
polyfillsStr = polyfillsStr.replace(/(.*?)$/, '└$1');
358376

359-
const polyfillsSize = (await util.promisify(gzip)(polyfillsAsset.source())).byteLength;
377+
const preamble = `[${NAME}] Completed in ${totalTime | 0}ms.${timingsStr}\n`;
378+
379+
if (!polyfillsAsset) {
380+
console.log(preamble + 'No polyfills bundle was created.');
381+
return;
382+
}
383+
384+
const polyfillsSize = polyfillsAsset ? (await util.promisify(gzip)(polyfillsAsset.source())).byteLength : 0;
360385
const polyfillsSizeStr = (polyfillsSize / 1000).toPrecision(3) + 'kB';
361386

362387
console.log(
363-
`[${NAME}] Completed in ${totalTime}ms.${timingsStr}\n` +
388+
preamble +
364389
`${polyfillsAsset._name} is ${polyfillsSizeStr} and bundles ${polyfills.length} polyfills:${polyfillsStr}`
365390
);
366391
}

0 commit comments

Comments
 (0)