首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Webpack 4迁移CommonsChunkPlugin

Webpack 4迁移CommonsChunkPlugin
EN

Stack Overflow用户
提问于 2018-02-28 04:47:25
回答 4查看 48.4K关注 0票数 49

我需要帮助将以下代码从webpack 3迁移到4。

代码语言:javascript
复制
new webpack.optimize.CommonsChunkPlugin({
    minChunks: module => module.context && module.context.indexOf("node_modules") !== -1,
    name: "vendor",
    chunks: ["main"]
})

我有两个条目文件,并且只希望第一个条目的依赖项包含在供应商块中。第二个条目的依赖项都应该保留在它自己的包中。

EN

回答 4

Stack Overflow用户

发布于 2018-03-11 03:16:34

我们已经弃用并删除了CommonsChunkPlugin,取而代之的是一组名为optimization.splitChunks的默认值和易于覆盖的接口。

代码语言:javascript
复制
webpack.optimize.CommonsChunkPlugin has been removed, 
please use config.optimization.splitChunks instead.

已弃用

您不再需要使用这些插件:

DedupePlugin has been removed too in v4

NoEmitOnErrorsPlugin optimization.noEmitOnErrors (生产模式下默认打开) NamedModulesPlugin -> optimization.noEmitOnErrors(生产模式下默认打开)NamedModulesPlugin -> optimization.namedModules (开发模式下默认打开)

对webpack 4的推荐

使用mini-css-extract-plugin而不是text-extract-plugin。使用webpack-bundle-analyzer以图形方式分析捆绑的输出。

入口脚本对于你的应用程序来说是真正的“入口脚本”,不要在webpack.config.js中显式地将供应商文件添加到entry:中。SPA应用程序有一个入口和多页面-像经典的ASP.NET MVC应用程序一样有多个入口点。Webpack将从你的入口脚本中构建依赖图,并为你的应用程序生成优化的捆绑包。

如果您想要从较早的webpack版本迁移,最好是签出migration guide

树抖动(死码消除)仅在生产模式下启用。

Webpack 4,捆绑资产的新方式

(你必须将你的CommonsChunkPlugin-thinking从你的头脑中移除)

!!! Meanwhile the webpack doc has been updated, a section SplitChunks was added !!!

It follows a new philosophy

现在,默认情况下,Webpack 4会自动执行优化。它会分析您的依赖关系图,并基于以下条件创建最佳包(输出):

  1. 可以共享新块或者模块来自node_modules文件夹
  2. 新块将大于30kb (在min+gz之前)
  3. 按需加载块时的最大并行请求数<= 5
  4. 初始页面加载时的最大并行请求数<= 3

所有这些都可以使用SplitChunksPlugin!(see SplitChunksPlugin documentation)进行调整。

A more detailed explanation,了解如何使用新的optimization.splitChunks应用编程接口。

CommonsChunkPlugin被删除,因为它有很多问题:

  • 它会导致下载的代码比所需的代码多。
  • 它对异步区块的效率很低。
  • 它很难使用。
  • 实现很难理解。

SplitChunksPlugin还有一些很棒的属性:

  • 它从不下载不需要的模块(只要您不通过名称执行区块合并)
  • 它在异步区块上的工作效率也很高
  • 对于异步区块它是默认启用的
  • 它可以处理多个供应商区块的供应商拆分
  • 它更易于使用
  • 它不依赖于区块图hacks
  • 大部分是自动的

--> Source

关于您的问题,您希望将entry1和entry2的所有部门拆分成单独的捆绑包。

代码语言:javascript
复制
      optimization: {
        splitChunks: {
          cacheGroups: {   
            "entry1-bundle": {
              test: /.../,   // <-- use the test property to specify which deps go here
              chunks: "all",
              name: "entry1-bundle",
 /** Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group */
              enforce: true,
              priority: ..  // use the priority, to tell where a shared dep should go
            },
            "entry2-bundle": {
              test: /..../, // <-- use the test property to specify which deps go here
              chunks: "all",
              name: "entry2-bundle",
              enforce: true,
              priority: ..
            }
          }
        }
      },

如果不添加优化:follows条目,则 如下所示

代码语言:javascript
复制
splitChunks: {
  chunks: 'async',
  minSize: 30000,
  minRemainingSize: 0,
  maxSize: 0,
  minChunks: 1,
  maxAsyncRequests: 6,
  maxInitialRequests: 4,
  automaticNameDelimiter: '~',
  automaticNameMaxLength: 30,
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true
    }
  }
}

您可以将optimization.splitChunks.cacheGroups.default设置为false以禁用默认缓存组,vendors缓存组也是如此!

下面是其他一些SplitChunks configuration examples的解释。

SplitChunksOptionsCachGroupOptionsOptimization的最新接口实现可以在here上找到。

下面的接口定义可能不是100%准确的,但对于简单的概述是很好的:

SplitChunksOptions 接口

代码语言:javascript
复制
interface SplitChunksOptions {
    /** Select chunks for determining shared modules (defaults to \"async\", \"initial\" and \"all\" requires adding these chunks to the HTML) */
    chunks?: "initial" | "async" | "all" | ((chunk: compilation.Chunk) => boolean);
    /** Minimal size for the created chunk */
    minSize?: number;
    /** Minimum number of times a module has to be duplicated until it's considered for splitting */
    minChunks?: number;
    /** Maximum number of requests which are accepted for on-demand loading */
    maxAsyncRequests?: number;
    /** Maximum number of initial chunks which are accepted for an entry point */
    maxInitialRequests?: number;
    /** Give chunks created a name (chunks with equal name are merged) */
    name?: boolean | string | ((...args: any[]) => any);
    /** Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks) */
    cacheGroups?: false | string | ((...args: any[]) => any) | RegExp | { [key: string]: CacheGroupsOptions };
}

CacheGroupsOptions interface:

代码语言:javascript
复制
interface CacheGroupsOptions {
    /** Assign modules to a cache group */
    test?: ((...args: any[]) => boolean) | string | RegExp;
    /** Select chunks for determining cache group content (defaults to \"initial\", \"initial\" and \"all\" requires adding these chunks to the HTML) */
    chunks?: "initial" | "async" | "all" | ((chunk: compilation.Chunk) => boolean);
    /** Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group */
    enforce?: boolean;
    /** Priority of this cache group */
    priority?: number;
    /** Minimal size for the created chunk */
    minSize?: number;
    /** Minimum number of times a module has to be duplicated until it's considered for splitting */
    minChunks?: number;
    /** Maximum number of requests which are accepted for on-demand loading */
    maxAsyncRequests?: number;
    /** Maximum number of initial chunks which are accepted for an entry point */
    maxInitialRequests?: number;
    /** Try to reuse existing chunk (with name) when it has matching modules */
    reuseExistingChunk?: boolean;
    /** Give chunks created a name (chunks with equal name are merged) */
    name?: boolean | string | ((...args: any[]) => any);
}

Optimization 接口

代码语言:javascript
复制
interface Optimization {
    /**
     *  Modules are removed from chunks when they are already available in all parent chunk groups.
     *  This reduces asset size. Smaller assets also result in faster builds since less code generation has to be performed.
     */
    removeAvailableModules?: boolean;
    /** Empty chunks are removed. This reduces load in filesystem and results in faster builds. */
    removeEmptyChunks?: boolean;
    /** Equal chunks are merged. This results in less code generation and faster builds. */
    mergeDuplicateChunks?: boolean;
    /** Chunks which are subsets of other chunks are determined and flagged in a way that subsets don’t have to be loaded when the bigger chunk has been loaded. */
    flagIncludedChunks?: boolean;
    /** Give more often used ids smaller (shorter) values. */
    occurrenceOrder?: boolean;
    /** Determine exports for each module when possible. This information is used by other optimizations or code generation. I. e. to generate more efficient code for export * from. */
    providedExports?: boolean;
    /**
     *  Determine used exports for each module. This depends on optimization.providedExports. This information is used by other optimizations or code generation.
     *  I. e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible.
     *  DCE in minimizers will benefit from this and can remove unused exports.
     */
    usedExports?: boolean;
    /**
     *  Recognise the sideEffects flag in package.json or rules to eliminate modules. This depends on optimization.providedExports and optimization.usedExports.
     *  These dependencies have a cost, but eliminating modules has positive impact on performance because of less code generation. It depends on your codebase.
     *  Try it for possible performance wins.
     */
    sideEffects?: boolean;
    /** Tries to find segments of the module graph which can be safely concatenated into a single module. Depends on optimization.providedExports and optimization.usedExports. */
    concatenateModules?: boolean;
    /** Finds modules which are shared between chunk and splits them into separate chunks to reduce duplication or separate vendor modules from application modules. */
    splitChunks?: SplitChunksOptions | false;
    /** Create a separate chunk for the webpack runtime code and chunk hash maps. This chunk should be inlined into the HTML */
    runtimeChunk?: boolean | "single" | "multiple" | RuntimeChunkOptions;
    /** Avoid emitting assets when errors occur. */
    noEmitOnErrors?: boolean;
    /** Instead of numeric ids, give modules readable names for better debugging. */
    namedModules?: boolean;
    /** Instead of numeric ids, give chunks readable names for better debugging. */
    namedChunks?: boolean;
    /** Defines the process.env.NODE_ENV constant to a compile-time-constant value. This allows to remove development only code from code. */
    nodeEnv?: string | false;
    /** Use the minimizer (optimization.minimizer, by default uglify-js) to minimize output assets. */
    minimize?: boolean;
    /** Minimizer(s) to use for minimizing the output */
    minimizer?: Array<Plugin | Tapable.Plugin>;
    /** Generate records with relative paths to be able to move the context folder". */
    portableRecords?: boolean;
}
}
票数 60
EN

Stack Overflow用户

发布于 2018-03-25 12:19:37

我有两个入口文件,并且只希望第一个入口文件的依赖项包含在供应商块中。第二个条目的依赖项都应该保留在它自己的包中。

假设入口点是mainsecondary

代码语言:javascript
复制
entry: {
    main: 'path-to/main.js',
    secondary: 'path-to/secondary.js'
}

使用webpack-4,您可以只从main块中提取vendors模块,而使用您想要创建的cacheGroupstest函数将secondary中引用的其他第三方模块保留在该块中。

代码语言:javascript
复制
optimization: {
    splitChunks: {
        cacheGroups: {
            vendors: {
                name: 'vendors',
                chunks: 'all',
                reuseExistingChunk: true,
                priority: 1,
                enforce: true,
                test(module, chunks) {
                    const name = module.nameForCondition && module.nameForCondition();
                    return chunks.some(chunk => {
                        return chunk.name === 'main' && /[\\/]node_modules[\\/]/.test(name);
                    });
                }
            },
            secondary: {
                name: 'secondary',
                chunks: 'all',
                priority: 2,
                enforce: true,
                test(module, chunks) {
                    return chunks.some(chunk => chunk.name === 'secondary');
                }
            }
        }
    }
}
票数 7
EN

Stack Overflow用户

发布于 2018-05-18 12:41:14

我花了一段时间才明白这一点,但对我来说关键的认识是,webpack 4中的chunks参数现在接受一个函数,它允许您只包含一个特定的条目。我假设这是一个最近的变化,因为在发帖的时候,官方文档中没有它。

代码语言:javascript
复制
splitChunks: {
  cacheGroups: {
    vendor: {
      name: 'vendor',
      chunks: chunk => chunk.name == 'main',
      reuseExistingChunk: true,
      priority: 1,
      test: module =>
        /[\\/]node_modules[\\/]/.test(module.context),
      minChunks: 1,
      minSize: 0,
    },
  },
},
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49017682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档