Cómo Webpack optimiza los archivos de configuración
Cuando se inicia Webpack, comenzará desde la entrada configurada, analizará la declaración de importación del archivo y luego realizará un análisis recursivo.
Webpack hará dos cosas cuando encuentre una declaración de importación:
1. Encuentre el archivo correspondiente a importar de acuerdo con la declaración de importación. Por ejemplo, require('react') importará el archivo ./node_modules/react/react.js, y require('./util') corresponde a ./util.js.
2. Utilice el cargador configurado para procesar el archivo según el sufijo que encontró para el archivo que desea importar. Por ejemplo, los archivos JavaScript desarrollados con ES6 deben procesarse con babel-loader.
Estas dos funciones son muy rápidas cuando se procesa un solo archivo, pero cuando el proyecto se hace más grande, la cantidad de archivos se vuelve muy grande, lo que expone el problema de la velocidad de compilación lenta.
Aunque estos dos puntos no se pueden evitar, para mejorar la velocidad es necesario reducirlos tanto como sea posible.
A continuación, presentaremos métodos para optimizar estos dos aspectos uno por uno.
Optimizar la configuración del cargador
Dado que la operación de conversión de archivos del cargador requiere mucho tiempo, desea que el cargador procese la menor cantidad de archivos posible.
En el Módulo 2-3, cubrimos cómo utilizar las pruebas, la inclusión y la exclusión para bloquear archivos para los cuales el cargador aplica reglas.
Para minimizar la cantidad de archivos procesados por el cargador, puede usar include para seleccionar solo los archivos que deben procesarse.
Por ejemplo, los pasos para configurar babel-loader para un proyecto usando ES6 son los siguientes:
module.exports = {
module: { p>
reglas: [
{
// Si solo hay archivos js en el código fuente del proyecto, no los escriba como /\?.jsx?$ / para mejorar el rendimiento de las expresiones regulares
test:/\.js$/,
// babel-loader admite el almacenamiento en caché de los resultados de conversión, habilitado a través de la opción cacheDirectory
uso: ['babel-loader?cacheDirectory'],
{
reglas: [
{
// / / Si solo hay js en el archivo de código fuente del proyecto, no escriba //. ],
// Utilice únicamente babel-loader para archivos en el directorio src bajo el directorio raíz del proyecto
incluya: path.resolve(dirname, 'src'),
},
]
},
};
Puede ajustar la estructura de directorios del proyecto para que cuando se carga la configuración. Es más fácil reducir el rango de aciertos al incluirlo cuando se usa un archivo .
Optimizar la configuración de resolve.modules
En 2-4 Resolve, resolve.modules se usa para configurar en qué directorios busca Webpack módulos de terceros.
El valor predeterminado de resolve.modules es ['node_modules'], lo que significa que primero ingresará al directorio actual./node_modules'], lo que significa que primero ingresará al directorio actual para encontrar el módulo que está buscando, si no existe. Si lo encuentra, vaya al directorio anterior ./node_modules, luego vaya a ./.../node_modules, etc. Esto es similar al mecanismo de búsqueda de módulos de Node.js.
Cuando todos los módulos de terceros instalados están ubicados en el directorio ./node_modules en el directorio raíz del proyecto, no es necesario buscar en las capas de forma predeterminada. Puede reducir el número de búsquedas especificando la ruta absoluta donde se almacenan los módulos de terceros, de la siguiente manera:
module.exports = {
resolve: {
// Utilice rutas absolutas para especificar la ubicación de módulos de terceros para reducir los pasos de búsqueda
// Utilice rutas absolutas para especificar la ubicación de módulos de terceros para reducir los pasos de búsqueda
módulo: [path.resolve (dirname, 'node_modules')]
},
};
Optimizar la configuración de resolve.mainFields
Como 2-4 Resolve Como se describe en, resolve.mainFields se usa para configurar qué archivo de entrada usa el módulo de terceros.
Cada módulo de terceros instalado tiene un archivo package.json, que describe las propiedades del módulo. Los campos que contiene describen la ubicación del archivo de entrada y resolve.mainFields se utiliza para configurar qué campo. utilizado como descripción del archivo de entrada.
La razón por la que puede haber varios campos que describen el archivo de entrada es porque algunos módulos se pueden usar en múltiples entornos al mismo tiempo y diferentes entornos requieren códigos diferentes.
Tomemos como ejemplo isomorphic-fetch, que es una implementación de la API de búsqueda pero que se puede utilizar en navegadores y entornos Node.js.
Hay 2 campos de descripción del archivo de entrada en su paquete.json:
{
"browser": "fetch-npm-browserify.js",
"main": "fetch-npm-node.js"
}
isomorphic-fetch usa código diferente en diferentes tiempos de ejecución, porque fetch La API está implementada de manera diferente, en el navegador a través de recuperación local o XMLHttpRequest, y en Node.js a través del módulo http.
El valor predeterminado de resolve.mainFields está relacionado con la configuración de destino actual, de la siguiente manera:
Cuando el destino es Web o webworker, su valor es ["browser", "module ", "main"]
Cuando el objetivo es cualquier otra cosa, su valor es ["module", "main"]. Cuando el objetivo son otras situaciones, el valor es ["módulo", "principal"]
Por ejemplo, cuando el objetivo es igual a web, Webpack primero utilizará el campo del navegador en el módulo de terceros para buscar el archivo de entrada del módulo, si no existe, se utiliza el campo del módulo, etc.
Para minimizar el número de pasos de búsqueda, puede configurar el campo de descripción del archivo de entrada del módulo de terceros en el menor número posible al especificarlo.
Dado que la mayoría de los módulos de terceros utilizan el campo principal para describir la ubicación del archivo de entrada, puede configurar Webpack de esta manera:
module.exports = {
resolve: {
// Utilice únicamente el campo principal como descripción del archivo de entrada, reduciendo así el número de pasos de búsqueda
// Utilice únicamente el campo principal, reduciendo así el número de pasos de búsqueda.
mainFields: ['main'],
},
};
Debe tener en cuenta al optimizar con este método. campos de descripción del archivo de entrada de todos los módulos de terceros de los que depende el tiempo de ejecución, incluso si uno de estos campos es incorrecto, puede provocar que el código creado no se ejecute normalmente.
Optimice la configuración de resolve.alias
En 2-4 Resolve, introdujimos el elemento de configuración resolve.alias, que asigna la ruta de importación original a la nueva ruta de importación a través de alias.
En proyectos reales, a menudo confiamos en algunos módulos enormes de terceros. Tomemos la biblioteca React, por ejemplo. La estructura de directorios de la biblioteca React instalada en el directorio node_modules es la siguiente:
├─ dist
│ ├─ react.js
│ └─ reaccionar .min.js
├─ reaccionar.min.js
├─ reaccionar.min.js
├─ reaccionar.min.js
├─ react.min.js
├─ lib
│ ...docenas de archivos ignorados
│ ├── LinkedStateMixin.js
│ ├─ createClass.js
│ └─ React.js
├─ paquete.json
│ └─ react.js
Puede ver que la biblioteca React publicada contiene dos conjuntos de código:
Un conjunto es código modular que usa la especificación CommonJS, que se coloca en el directorio lib y usa el paquete La entrada El archivo react.js especificado en .json sirve como punto de entrada del módulo.
Un conjunto es un paquete completo que contiene todo el código relacionado con React en un solo archivo y se puede ejecutar directamente sin modularización. dist/react.js se utiliza como entorno de desarrollo y contiene código para comprobaciones y advertencias. dist/react.min.js es para entornos en línea y está minimizado.
De forma predeterminada, Webpack comienza con el archivo de entrada ./node_modules/react/react.js y analiza y procesa de forma recursiva docenas de dependencias, lo que puede ser una operación que requiere mucho tiempo.
La configuración de resolve.alias permite a Webpack usar un único y completo archivo react.min.js cuando usa la biblioteca React, omitiendo así la resolución recursiva que requiere mucho tiempo.
La configuración de Webpack relevante es la siguiente:
module.exports = {
resolve: {
// Usar alias para importar reaccionar Reemplace la declaración con un archivo react.min.js completo
// Reduzca las operaciones de análisis recursivas que consumen mucho tiempo
Alias: {
'react': ruta .resolve(dirname, './node_modules/react/dist/react.min.js'),
}
},
};
}; p>
Con la excepción de la biblioteca React, la mayoría de las bibliotecas se publican en repositorios Npm como paquetes completos y puede configurar alias para estas bibliotecas.
Pero para algunas bibliotecas, el uso de esta optimización interferirá con la optimización de agitación de árboles (usada para eliminar el código inactivo) que analizaremos más adelante, porque es posible que parte del código del archivo del paquete completo nunca se use. en tu proyecto.
Este método se suele utilizar para bibliotecas con una gran integridad, porque el código del archivo completo es un todo y cada línea es crucial.
Pero para las bibliotecas instrumentadas (como lodash), es posible que su proyecto solo use algunas de las funciones instrumentadas, por lo que no puede usar este método para la optimización porque generará una gran cantidad de nunca El código se ejecutado.
Optimizar la configuración de resolve.extensions
Cuando la declaración de importación no tiene una extensión de archivo, Webpack agregará automáticamente la extensión e intentará preguntar si el archivo existe.
Como se describe en 2-4 Resolve, resolve.extensions se utiliza para configurar la lista de extensiones utilizadas durante el intento. El valor predeterminado es:
extensiones: ['.js', ' .json']
Esto significa que cuando encuentre un archivo como require('./data') , Webpack primero buscará el archivo ./data.js, y si ese archivo no existe , buscará el archivo ./data.json y, si aún no lo encuentra, informará un error.
Si la lista es más larga, o si el sufijo correcto aparece más tarde, habrá más intentos, por lo que la configuración de resolve.extensions también afectará el rendimiento de la compilación.
Al configurar resolve.extensions, debe cumplir con los siguientes puntos para optimizar el rendimiento de la compilación tanto como sea posible:
Mantenga la lista de intentos de sufijo lo más estrecha posible y no escribir situaciones que no son posibles en el proyecto Ingrese la lista de intentos de sufijos.
Los sufijos de archivos con mayor frecuencia deben clasificarse en primer lugar para poder salir del proceso de búsqueda lo antes posible. Al escribir declaraciones de importación en el código fuente, utilice sufijos siempre que sea posible para evitar el proceso de búsqueda. Por ejemplo, escriba require('./data') como require('./data.json').
La configuración de Webpack relevante es la siguiente:
module.exports = {
resolve: {
// Reducir el número de intentos de sufijo tanto como sea posible Posibilidad
extensiones: ['js'],
},
}; Configuración de noParse
Como se describe en el Módulo 2-3, el elemento de configuración module.noParse permite a Webpack ignorar el análisis recursivo de archivos no modularizados, mejorando así el rendimiento de la compilación.
La razón de esto es que algunas bibliotecas, como jQuery y ChartJS, son tan grandes y no modulares que no tiene sentido que Webpack las analice.
En la configuración optimizada de resolve.alias anterior, hablamos de que el archivo react.min.js completo en sí no es modular, así que configuremos module.noParse para ignorar el análisis recursivo de react.min.js. archivos.
A continuación se explica cómo configurar la configuración del paquete web relevante:
const path = require('path');
module.exports = {
módulo: {
// El archivo único y completo `react.min.js` no está modularizado y se ignora el análisis recursivo de los archivos `react.min.js`.
noParse: [/react\.min\.js$/],
},
},
};
Tenga en cuenta que los archivos ignorados no deben contener declaraciones modulares como import, require, define, etc., ya que esto hará que el código creado contenga declaraciones modulares que no son ejecutables en el entorno del navegador.
Los archivos ignorados no deben contener declaraciones modulares como import, require y define.
Creo que después de leer este artículo, domina este método. Para obtener más información interesante, preste atención a otros artículos relacionados de Gxl net.
Lectura recomendada:
AngularJS implementa el juego de adivinar números
Angular implementa efectos de complemento que pueden agregar, eliminar y calcular la cantidad total