简体   繁体   English

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

[英]Use Webpack to split out a module so that it can be loaded in a WebWorker

I have a web app that I compile with webpack. 我有一个web应用程序,我用webpack编译。 One of the modules that my code uses is named table.js . 我的代码使用的其中一个模块名为table.js Until recently, it's just been another module and has been compiled into my bundle.js file with everything else. 直到最近,它只是另一个模块,并已编译到我的bundle.js文件中的所有其他内容。

Now I need to run table.js in a Web Worker, so I need to pull it and its dependencies into a separate file that can be loaded both standalone and by my other modules. 现在我需要在Web Worker中运行table.js ,所以我需要将它和它的依赖项拉到一个单独的文件中,该文件可以单独加载,也可以由我的其他模块加载。

At first I thought to include table.js in my webpack.config.js 's entry . 起初我想在我的webpack.config.jsentry包含table.js

var config = {
    ...
    entry: {
        app: [ './src/main.js', './src/classes/table.js' ],
        vendors: [],
    },
    ...
}

That didn't work. 那没用。 Then I thought to separate it out like my vendors bundle. 然后我想像我的供应商捆绑一样把它分开。

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'));

This seems to pull Table and its dependencies into a chunk of bundle.js , 1.bundle.js . 这似乎将Table及其依赖项拉入了bundle.js1.bundle.js一大块。 Unfortunately, then calling import Table from 'table' causes this error: 不幸的是,然后import Table from 'table'调用import Table from 'table'会导致此错误:

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

I also have a circular dependency between TableStore and Table . 我在TableStoreTable之间也有一个循环依赖。 TableStore needs to stay in bundle.js because it shouldn't be loaded into the Web Worker. TableStore需要保留在bundle.js因为它不应该加载到Web Worker中。 Previously, when I've needed to throw things into a separate chunk, I've done: 以前,当我需要把东西扔进一个单独的块时,我已经完成了:

if (someThingNeedsRequiring) {
    require.ensure([], () => {
        require('something');
    }
}

With the circular dependency, this doesn't seem to work. 由于循环依赖,这似乎不起作用。

/* 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';

Could someone set me straight on the correct way to have my webpack.config.js and how to use my import s in my module files? 有人可以让我直接找到我的webpack.config.js以及如何在我的模块文件中使用我的import的正确方法吗?

(It's been quite a while since I figured this out, and I haven't touched the project in nearly six months, so I may have missed some of the details. Comment if it's not working, and I'll try to figure out what I'm missing.) (已经有一段时间了,因为我发现了这个问题,而且我近六个月没有接触到这个项目,所以我可能错过了一些细节。评论一下它是否有效,我会试着找出什么我迷路了。)

webpack.config webpack.config

It turns out there are two handy-dandy JavaScript packages for doing what I want: worker-loader and workerjs . 事实证明,有两个方便的dandy JavaScript包可以做我想要的: worker-loaderworkerjs

npm install --save workerjs worker-loader

I added this in my webpack.config.js: 我在webpack.config.js中添加了这个:

var config = {
    // ...

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

    // ...
}

require() 要求()

In order to specify that I want my class to be run in a WebWorker file, my require looks like: 为了指定我希望我的类在WebWorker文件中运行,我的需要如下所示:

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

// ecmaScript 5
var TableWorker = require('worker?name=tableRoller!path/to/table');

TableWorker is just a variable name I used for table.js's export default class Table {...} . TableWorker只是我用于table.js的export default class Table {...}的变量名。 The name=tableRoller specifies the generated outputted [name].worker.js filename. name=tableRoller指定生成的输出[name].worker.js文件名。 For example, I have another WebWorker named distCalc.worker.js , so my import looks like: 例如,我有另一个名为distCalc.worker.js WebWorker,所以我的import如下:

import DistWorker from 'worker?name=distCalc!path/to/distWorker';

Note that in this case, distWorker only ever runs in a WebWorker, while Table is used in both my main.js entry point and my tableRoller.worker.js WebWorker file. 请注意,在这种情况下, distWorker只能在WebWorker中运行,而Table在我的main.js入口点和tableRoller.worker.js WebWorker文件中使用。

workerjs and worker-loader generate a new entry point file and pull in all of the dependencies of those classes. workerjsworker-loader生成一个新的入口点文件,并提取这些类的所有依赖项。 Tobias Koppers (worker-loader) and Eugene Ware (workerjs) are geniuses. Tobias Koppers(工人装载者)和Eugene Ware(工人家庭)是天才。

Detecting WebWorker 检测WebWorker

My _inWebWorker detection is: 我的_inWebWorker检测是:

let _inWebWorker = typeof Window === 'undefined';

Change output filename in your webpack.config.js file 更改webpack.config.js文件中的输出文件名

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

then Webpack can separate your entries with its name in dist directory. 然后Webpack可以将您的条目与dist目录中的名称分开。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM