使用Webpack拆分模块,以便可以将其加载到WebWorker中

dx_*_*_dt 7 javascript node.js webpack

我有一个web应用程序,我用webpack编译.我的代码使用的模块之一就是命名table.js.直到最近,它只是另一个模块,并已编译到我的bundle.js文件与其他一切.

现在我需要table.js在Web Worker中运行,所以我需要将它和它的依赖项拉到一个单独的文件中,该文件既可以单独加载,也可以由我的其他模块加载.

起初我想包括table.js在我webpack.config.jsentry.

var config = {
    ...
    entry: {
        app: [ './src/main.js', './src/classes/table.js' ],
        vendors: [],
    },
    ...
}
Run Code Online (Sandbox Code Playgroud)

那没用.然后我想像我的供应商捆绑一样把它分开.

var config = {
    /* for vendors (and other modules) we have a CDN for */
    addExternal: function (name, globalVar) {
        this.externals[name] = globalVar;
        this.entry.vendors.push(name);
    },

    /* for vendors we don't have a CDN for */
    addVendor: function (name, path) {
        this.resolve.alias[name] = path;
        this.entry.vendors.push(name);
    },

    addPlugin: function (plugin) {
        this.plugins.push(plugin);
    },

    entry: {
        app: [ './src/main.js' ],
        vendors: [],
        table: [ __dirname + '/src/classes/table.js' ]
    },

    plugins: [],

    externals: { },

    output: {
        path: __dirname + '/public/dist/',
        filename: 'bundle.js',
        publicPath: '/dist/',
        sourceMapFile: '[file].map'
    },

    resolve: {
        alias: { 'table': './src/classes/table.js' },
        extensions: [ '', '.js', '.jsx' ]
    },
    ...
}

/* add vendors and externals */
...

config.addPlugin(new CommonsChunkPlugin('vendors', 'vendors.js'));
config.addPlugin(new CommonsChunkPlugin('table', 'table.js'));
Run Code Online (Sandbox Code Playgroud)

这似乎拉表和它的依赖到了一大块bundle.js,1.bundle.js.不幸的是,然后调用import Table from 'table'导致此错误:

ERROR in CommonsChunkPlugin: While running in normal mode it's not allowed to use a non-entry chunk (table)
Run Code Online (Sandbox Code Playgroud)

TableStore和之间也有一个循环依赖Table. TableStore需要保留,bundle.js因为它不应该加载到Web Worker中.以前,当我需要把东西扔进一个单独的块时,我已经完成了:

if (someThingNeedsRequiring) {
    require.ensure([], () => {
        require('something');
    }
}
Run Code Online (Sandbox Code Playgroud)

由于循环依赖,这似乎不起作用.

/* table.js */
let _inWebWorker = self instanceof Window,
    TableStore = null;

if (!_inWebWorker) {
    require.ensure([], function() { TableStore = require('../stores/table-store'); } );
}

/* table-store.js */
import Table from 'table';
Run Code Online (Sandbox Code Playgroud)

有人可以让我直截了当地让我webpack.config.jsimport我的模块文件中使用我的s吗?

dx_*_*_dt 7

(已经有一段时间了,因为我发现了这个问题,而且我近六个月没有接触到这个项目,所以我可能错过了一些细节.评论一下它是否有效,我会试着找出什么我迷路了.)

webpack.config

事实证明,有两个方便的dandy JavaScript包用于做我想要的事情:worker-loaderworkerjs.

npm install --save workerjs worker-loader
Run Code Online (Sandbox Code Playgroud)

我在webpack.config.js中添加了这个:

var config = {
    // ...

    worker: {
        output: {
            filename: '[name].worker.js',
            chunkFilename: '[name].worker.js'
        }
    },

    // ...
}
Run Code Online (Sandbox Code Playgroud)

要求()

为了指定我希望我的类在WebWorker文件中运行,我的需要如下所示:

// ecmaScript 6
import TableWorker from 'worker?name=tableRoller!path/to/table';

// ecmaScript 5
var TableWorker = require('worker?name=tableRoller!path/to/table');
Run Code Online (Sandbox Code Playgroud)

TableWorker只是我用于table.js的变量名export default class Table {...}.的name=tableRoller指定生成的输出[name].worker.js文件名.例如,我有另一个名为的WebWorker distCalc.worker.js,所以我import看起来像:

import DistWorker from 'worker?name=distCalc!path/to/distWorker';
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,distWorker只能在WebWorker中运行,而Table在我的main.js入口点和tableRoller.worker.jsWebWorker文件中都使用它.

workerjsworker-loader生成一个新的入口点文件,并提取这些类的所有依赖项.Tobias Koppers(工人装载者)和Eugene Ware(工人家庭)是天才.

检测WebWorker

我的_inWebWorker检测是:

let _inWebWorker = typeof Window === 'undefined';
Run Code Online (Sandbox Code Playgroud)