如何创建具有单独捆绑的依赖关系的捆绑包

时间:2019-02-22 16:17:30

标签: javascript webpack bundling-and-minification webpack-4 code-splitting

我需要为第三方插件创建一个JavaScript框架,该插件可以使用它想要的任何依赖关系以及依赖关系的任何版本,而又不会与同一页面上使用的其他第三方插件冲突。 / p>

我还必须考虑共享插件之间的依赖关系,以免最终得到x个使用相同依赖关系和版本的插件,并以x个相同依赖关系使页面膨胀。 >

我最初的想法是使用Webpack捆绑第三方插件,但我需要为每个单独的依赖项单独包装以减少页面膨胀。因此,我将此配置添加到了webpack的配置中:

module.exports = {
    entry: {
        pluginX: './src/index.js',
    },
    devtool: 'source-map',
    target: 'web',
    output: {
        path: path.resolve(__dirname, './dist'),
        library: 'pluginX',
    },
    optimization: {
        moduleIds: 'named',
        chunkIds: 'named',        
        splitChunks: {
            chunks: 'all',
            name(module, chunk, cacheGroupKey) {
                const context = module.context;
                const splitContext = context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/);

                const packageJson = getPackageJson(context);
                const version = packageJson ? packageJson.version : '0.0.0';
                const name = splitContext[1].replace('@', '');
                return `${cacheGroupKey}-${name}-${version}`;
            },
        }
    },
    plugins: [
        new CleanPlugin('./dist', {
            verbose: false,
        }),
    ]
}

getPackageJson函数如下所示:

function getPackageJson(context) {
    do {
        const packageJson = `${context}\\package.json`;
        if (fs.existsSync(packageJson)) { return require(packageJson); }
        const splits = context.split(/\\/);
        splits.pop();
        context = splits.length > 0 ? splits.join('\\') : undefined;
    } while (context);
    return undefined;
}

我已经设置了三个测试插件,一个使用d3 v5.9.1,另外两个使用d3 v3.5.17。使用此配置,我可以正确地分别捆绑插件及其依赖项,我创建了一个测试服务器来服务捆绑的条目捆绑包和依赖项捆绑包。使用d3 v5.9.1的插件1似乎可以正常工作,但是插件2和插件3永远无法协同工作;当我尝试访问插件名称(在output.library属性中指定)时,其中之一将始终是未定义的。

作为参考,这是index.html页面:

<!DOCTYPE html>
<html>

<head>
    <script src="./vendors-d3-3.5.17.js" type="text/javascript"></script>
    <script src="./vendors-d3-5.9.1.js" type="text/javascript"></script>
    <script src="./plugin1.js" type="text/javascript"></script>
    <script src="./plugin2.js" type="text/javascript"></script>
    <script src="./plugin3.js" type="text/javascript"></script>
</head>

<body></body>

</html>

我正在使用的HtmlWebpackPlugin自动添加了index.js(我正在使用webpack-dev-server进行测试)。

作为测试页面的index.js页面是这样的:

setTimeout(function () {
    plugin1.run();
    plugin2.run();
    plugin3.run();
}, 1000);

插件1 index.js文件如下所示:

import * as d3 from 'd3';

export function run() {
    console.log('plugin1', !!d3.scaleLinear, !!(d3.scale || {}).linear);
}

插件2和3将此作为其index.js文件:

import * as d3 from 'd3';

export function run() {
    console.log('pluginX', !!d3.scale.linear, !!d3.scaleLinear);
}

控制台输出应为:

plugin1 true false
plugin2 true false
plugin3 true false

但是我实际上得到了其中一个:

plugin1 true false
plugin2 true false
Uncaught TypeError: Cannot read property 'run' of undefined

或者这个:

plugin1 true false
Uncaught TypeError: Cannot read property 'run' of undefined

因为plugin2或plugin3(总是只有其中之一)始终未定义。

我怀疑这与webpack插入的引导程序代码有关,但我不能100%确定。

0 个答案:

没有答案