简体   繁体   English

Webpack 中具有多个供应商捆绑包的多个入口点

[英]Multiple Entry Points with Multiple Vendor Bundles in Webpack

I've got several 'single-page apps' that need to run side-by-side in a single overarching application.我有几个“单页应用程序”需要在一个总体应用程序中并排运行。 To that end, I'm using webpack to trigger transpilation for jsx and scss, bundle the resulting css and js, and split application code written by us and application code that's coming in from third-party sources.为此,我使用 webpack 触发 jsx 和 scss 的转换,捆绑生成的 css 和 js,并将我们编写的应用程序代码与来自第三方来源的应用程序代码分开。

Unfortunately, it seems like webpack is very opinionated on how it bundles the vendor files - it wants to create a single large vendor bundle for all my entry points instead of a more reasonable split like this:不幸的是,webpack 似乎对它如何捆绑供应商文件非常固执己见——它想为我的所有入口点创建一个单一的大型供应商捆绑包,而不是像这样更合理的拆分:

- app1
    - app1.bundle.js
    - app1.vendor.bundle.js
    - app1.bundle.css
- app2
    - app2.bundle.js
    - app2.vendor.bundle.js
    - app2.bundle.css

I specifically don't want to run into the situation where I import some large (eg, JQuery) library into app 2 and have it included along in the vendor bundles for other apps that don't need it.我特别不想遇到我将一些大型(例如,JQuery)库导入应用程序 2 并将其包含在供应商捆绑包中以供其他不需要它的应用程序使用的情况。 Many of our pages use totally different front-end stacks, and if I used a single vendor.js file for the entire web app I could see this ballooning out of control very quickly.我们的许多页面使用完全不同的前端堆栈,如果我为整个 web 应用程序使用单个vendor.js文件,我会很快看到这种膨胀失控。

I'd also prefer to have this done automatically - webpack should be able to scan through my entry point, detect which third-party libraries (probably by referencing node-modules?) are being imported, and only include those in the vendor file for that app.我也希望自动完成这项工作 - webpack 应该能够扫描我的入口点,检测正在导入哪些第三方库(可能通过引用节点模块?),并且只将那些包含在供应商文件中那个应用程序。 I don't want to have to add third-party dependencies into an array in my webpack config and require() them in my entry point.我不想将第三方依赖项添加到我的 webpack 配置中的数组中,在我的入口点中require()它们。 That seems very redundant.这似乎很多余。

I'm okay with app1.vendor.bundle.js and app2.vendor.bundle.js having overlap (ie, if they both import React, they can both include that code in their separate bundles).app1.vendor.bundle.jsapp2.vendor.bundle.js有重叠(即,如果它们都导入 React,它们都可以在各自的包中包含该代码)。 I consider this a lot easier to manage than having to deal with common files that are shared between some subset of the apps running on my site.我认为这比处理在我网站上运行的某些应用程序子集之间共享的公共文件更容易管理。

Is there any way to actually do this in webpack on its own, or am I going to have to write some kind of custom solution that wraps around it to do this?有没有办法在 webpack 中单独执行此操作,或者我是否必须编写某种围绕它的自定义解决方案来执行此操作? All the examples I've seen have people compiling a single overarching vendor bundle for their entire application.我见过的所有示例都让人们为他们的整个应用程序编译一个单一的总体供应商包。

It's good to note that webpack supports an array of configurations.值得注意的是 webpack 支持一系列配置。 In that case, you would write something like this:在那种情况下,你会写这样的东西:

webpack.config.js webpack.config.js

module.exports = [
  {...}, // Your first config
  {...}, // Your second config
]

Using this approach, you could write a configuration per page.使用这种方法,您可以为每页编写一个配置。

To generate entry HTML, you could use something like html-webpack-plugin or mini-html-webpack-plugin .要生成条目 HTML,您可以使用html-webpack-pluginmini-html-webpack-plugin 之类的东西

If you inject the bundles to your HTML otherwise, then it's useful to extract a manifest ( webpack-manifest-plugin , webpack-assets-manifest ).如果您以其他方式将捆绑包注入 HTML,那么提取清单( webpack-manifest-pluginwebpack-assets-manifest )会很有用。 That gives you a JSON you can then use to inject the HTML you need at your host environment.这为您提供了一个 JSON,然后您可以使用它在您的主机环境中注入您需要的 HTML。

Maybe you can use one webpack.config.js for each app , with entrypoint set to that app. 也许你可以为每个应用程序使用一个webpack.config.js ,并将入口点设置为该应用程序。 (even if they share the same node_modules ) (即使它们共享相同的node_modules

Like this: 像这样:

config/
  base.webpack.config.js
  app1.webpack.config.js
  app2.webpack.config.js
  ...
build.sh

base.webpack.config.js base.webpack.config.js

// your main webpack config with `splitChunks` config etc.
module.exports = {
  ...
  optimization: {
    splitChunks: {
      minChunks: ...,
      cacheGroups: {
        vendors: { ... }
      }
    }
  }
};

app1.webpack.config.js app1.webpack.config.js

// config for app1
const baseConfig = require('./base.webpack.config');

module.exports = {
  ...baseConfig,
  entry: {
    app: '../src/app1.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, '..', 'dist/app1')
  }
};

build.sh build.sh

#!/bin/sh
# build app1
webpack --config config/app1.webpack.config.js

# build app2
webpack --config config/app2.webpack.config.js

I may have what you're looking for (based on webpack 5)...我可能有你要找的东西(基于 webpack 5)...

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // minifies your CSS
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    entry: {
        'app1': './src/app1.js',
        'app2': './src/app2.js'
    },
    output: {
        filename: '[name].bundle.[contenthash].js', // <-- NAME WILL MATCH YOUR ENTRY POINTS, contenthash generates a hash to prevent any  caching on an updated version of your file
        path: path.resolve(__dirname, './dist'),
        publicPath: ''
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, 'css-loader'
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].bundle.[contenthash].css' // <-- SAME HERE FOR CSS
        }),
        new CleanWebpackPlugin() <-- clean the /dist folder, avoid ending up with X versions of your files because of a new hashed version generated with the use of [contenthash] in your filenames
    ]
};
```

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

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