splitchunks chunk cachegroups javascript webpack webpack-3 commonschunkplugin webpack-4

javascript - cachegroups - webpack chunks



Webpack 4 migraciĆ³n CommonsChunkPlugin (3)

Necesito ayuda para migrar el siguiente código del paquete web 3 al 4.

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

Tengo dos archivos de entrada y quiero que solo se incluyan las dependencias de la primera en la parte del proveedor. Las dependencias de la segunda entrada deben permanecer todas en su propio paquete.


Tengo dos archivos de entrada y quiero que solo se incluyan las dependencias de la primera en la parte del proveedor. Las dependencias de la segunda entrada deben permanecer todas en su propio paquete.

Asumiendo que tus puntos de entrada son main y secondary :

entry: { main: ''path-to/main.js'', secondary: ''path-to/secondary.js'' }

Uso de webpack-4 Puede extraer solo los módulos de los vendors de la parte main pero deje los módulos de terceros a los que se hace referencia en la parte secondary utilizando la función de test de los cacheGroups de cacheGroups que desea crear.

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


Esto me llevó un tiempo descifrarlo, pero la realización clave para mí fue que el argumento de los chunks en el webpack 4 ahora tiene una función, que le permite incluir solo una entrada específica. Supongo que esto es un cambio reciente, porque en el momento de la publicación no estaba en la documentación oficial.

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, }, }, },


A partir del webpack v4, el CommonsChunkPlugin está en desuso.

Hemos desaprobado y eliminado CommonsChunkPlugin, y lo hemos reemplazado con un conjunto de valores predeterminados y una API fácilmente reemplazable llamada optimization.splitChunks .

webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.

Obsoleto

Ya no necesitas usar estos complementos:

DedupePlugin se ha eliminado también en v4

NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors ( activado de manera predeterminada en el modo de producción) ModuleConcatenationPlugin -> optimization.concatenateModules ( activado de forma predeterminada en el modo prod) NamedModulesPlugin -> optimization.namedModules

Recomendaciones para webpack 4.

Use mini-css-extract-plugin lugar de text-extract-plugin . Utilice webpack-bundle-analyzer para analizar su salida en paquete de forma gráfica.

Los scripts de entrada son "Scripts de entrada" reales para su aplicación, no agregue los archivos de proveedores explícitamente a la entry: en webpack.config.js . Las aplicaciones SPA tienen una entrada y las aplicaciones de varias páginas, como las ASP.NET MVC clásicas, tienen múltiples puntos de entrada. Webpack creará un gráfico de dependencia a partir de sus scripts de entrada y generará paquetes optimizados para su aplicación.

Si desea migrar desde una versión anterior de un paquete web, es mejor consultar la guía de migración.

La agitación de árboles (eliminación de código muerto) solo está habilitada en el modo de producción.

Webpack 4, la nueva forma de agrupar activos.

( Tienes que eliminar tu CommonsChunkPlugin-thinking de tu cabeza )

!!! Mientras tanto, el webpack doc se ha actualizado, se agregó una sección SplitChunks !!!

Sigue una nueva filosofía :

Webpack 4 ahora por defecto hace optimizaciones automáticamente. Analiza su gráfico de dependencia y crea paquetes óptimos (salida), en base a las siguientes condiciones:

  1. Los nuevos chunk pueden ser compartidos O los módulos son de la carpeta node_modules
  2. La nueva porción sería más grande que 30kb (antes de min + gz)
  3. Número máximo de solicitudes paralelas cuando se cargan trozos a pedido <= 5
  4. Número máximo de solicitudes paralelas en la carga de la página inicial <= 3

¡Todo esto puede ser ajustado usando el SplitChunksPlugin! ( ver la documentación de SplitChunksPlugin )

Una explicación más detallada sobre cómo usar la nueva API optimization.splitChunks .


CommonsChunkPlugin se eliminó porque tiene muchos problemas:

  • Puede resultar en que se descargue más código del que se necesita.
  • Es ineficiente en trozos asíncronos.
  • Es difícil de usar.
  • La implementación es difícil de entender.

El SplitChunksPlugin también tiene algunas grandes propiedades:

  • Nunca descarga un módulo innecesario (siempre que no haga cumplir la fusión de fragmentos a través del nombre)
  • Funciona de manera eficiente en trozos asíncronos también
  • Está activado por defecto para trozos asíncronos.
  • Maneja la división de proveedores con múltiples partes de proveedores
  • Es mas facil de usar
  • No se basa en hacks gráficos de trozos
  • En su mayoría automáticos

-> Fuente

Con respecto a su problema , desea dividir todos los deps de entry1 y entry2 en paquetes separados.

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: .. } } } },

Si no agrega la entrada de optimización: splitChunks, la configuración predeterminada es la siguiente :

splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: ''~'', name: true, cacheGroups: { vendors: { test: /[///]node_modules[///]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }

Puede establecer optimization.splitChunks.cacheGroups. predeterminado a falso para deshabilitar el grupo de caché predeterminado , igual para el grupo de caché de proveedores !

Las implementaciones de interfaz actualizadas para SplitChunksOptions , CachGroupOptions y Optimization se pueden encontrar here .

Las siguientes definiciones de interfaz pueden no ser 100% precisas, pero son buenas para una descripción simple:

Interfaz SplitChunksOptions

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 }; }

Interfaz de CacheGroupsOptions :

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

Interfaz de Optimization

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; } }