Como "león de asedio" de front-end, Webpack es muy familiar. Puede empaquetar todos los recursos (incluidos JS, TS, JSX, imágenes, fuentes, CSS, etc.) y colocarlos en dependencias. ., permitiéndole hacer referencia a dependencias para utilizar los recursos según sus necesidades. Webpack ha hecho un excelente trabajo al traducir múltiples recursos de archivos en el front-end y analizar dependencias de módulos complejos. También podemos personalizar el cargador y cargar nuestros propios recursos. Entonces, ¿cómo implementa Webpack el empaquetado? Ven y echa un vistazo hoy.
1. ¿Qué se requiere?
Cuando se trata de requerir, lo primero que viene a la mente es importar. Importar es un estándar de sintaxis de es6;
requerir es una llamada en tiempo de ejecución, por lo que, en teoría, se puede usar en cualquier parte del código;
importar es un tiempo de compilación
;llamada, por lo que debe colocarse al principio del archivo.
Cuando usamos Webpack para compilar, usaremos babel para traducir la importación a require. En CommonJS, existe un método global require (), que se usa para cargar módulos. AMD y CMD también utilizan el método require como referencia.
Por ejemplo:
var add = require('./a.js');En términos simples,
add(1,2)
requiere es en realidad una función, y el ./a.js
al que se hace referencia es solo un parámetro de la función.
2. ¿Qué son las exportaciones?
Aquí podemos pensar en las exportaciones como un objeto. Puede ver el uso específico de la exportación MDN.
Primero veamos la estructura del código después de nuestro empaque. Podemos encontrar que las exportaciones aparecerán después del empaque.
No todos los navegadores pueden ejecutar require exports. Debe implementar require y exports usted mismo para garantizar el funcionamiento normal del código. El código empaquetado es una función autoejecutable. Los parámetros tienen información de dependencia y el código del archivo ejecuta el código a través de eval.
El dibujo de diseño general es el siguiente:
Paso 1: Escriba nuestro archivo de configuración.
El archivo de configuración configura nuestra entrada empaquetada y nuestra salida empaquetada para preparar los archivos generados posteriormente.
ruta constante = requerir("ruta"); módulo.exportaciones = { entrada: "./src/index.js", producción: { ruta: path.resolve(__dirname, "./dist"), // La dirección del archivo resultante después del empaquetado requiere una ruta absoluta, por lo que se requiere la ruta nombre de archivo: "principal.js" }, modo: "desarrollo"
Paso 2: La idea general del análisis del módulo
: En resumen, es utilizar el archivo fs para leer el archivo de entrada y obtener la ruta del archivo dependiente de la importación a través de AST, si el archivo dependiente aún. tiene dependencias, siga recurriendo hasta que el análisis de dependencia sea claro y se mantenga en un mapa.
Desglose detallado : Algunas personas pueden preguntarse por qué se usa AST, porque AST nace con esta función. Su ImportDeclaration puede ayudarnos a filtrar rápidamente la sintaxis de importación. Por supuesto, también es posible usar coincidencias regulares. cadena después de ser leída Al escribir The awesome regex es útil para obtener rutas de dependencia de archivos, pero no es lo suficientemente elegante.
archivo index.js
import { str } from "./a.js"; console.log(`${str} Webpack`)
un archivo.js
importa {b} desde "./b.js" export const str = "hola"
archivo b.js
export const b="bbb"
el análisis del módulo Webpack: use @babel/parser de AST para convertir la cadena leída del archivo en un árbol AST y @babel/traverse para sintaxis Analice y utilice ImportDeclaration para filtrar importaciones y encontrar dependencias de archivos.
contenido constante = fs.readFileSync(entryFile, "utf-8"); const ast = parser.parse(contenido, { tipo fuente: "módulo" }); const dirname = ruta.dirname(entryFile); dependientes constantes = {}; atravesar(ast, { Declaración de importación ({ nodo }) { //Filtrar importaciones const newPathName = "./" + ruta.join(dirname, node.source.value); dependientes[nodo.fuente.valor] = nuevoNombreRuta; } }) const {código} = transformFromAst(ast, null, { ajustes preestablecidos: ["@babel/preset-env"] }) devolver { archivo de entrada, dependientes, código }
Los resultados son los siguientes:
Utilice recursividad o bucle para importar archivos uno por uno para el análisis de dependencias. Tenga en cuenta que utilizamos el bucle for para analizar todas las dependencias. La razón por la que los bucles pueden analizar todas las dependencias es que la longitud de los módulos cambia cuando hay dependencias.modules. nuevas dependencias, module.length cambiará.
for (sea i = 0; i < this.modules.length; i++) { elemento constante = this.modules[i]; const {dependientes} = artículo; si (dependientes) { for (sea j en dependientes) { this.modules.push(this.parse(dependientes[j])); } } }
Paso 3: Escriba la función WebpackBootstrap + genere el archivo de salida.
Escriba la función WebpackBootstrap : Lo primero que debemos hacer aquí es la función WebpackBootstrap. Después de la compilación, la importación de nuestro código fuente se analizará en require. no reconoce require, entonces debemos declararlo primero. Después de todo, require es un método al escribir funciones, también debe prestar atención al aislamiento del alcance para evitar la contaminación variable. También necesitamos declarar las exportaciones en nuestro código para asegurarnos de que ya existan cuando se ejecuta el código.
Genere el archivo de salida : ya hemos escrito la dirección del archivo generado en el archivo de configuración y luego usamos fs.writeFileSync para escribirlo en la carpeta de salida.
archivo (código) { const filePath = ruta.unirse(esta.salida.ruta, este.salida.nombre de archivo) const nuevoCódigo = JSON.stringify(código); // Generar contenido del archivo de paquete const paquete = `(función(módulos){ función requiere (módulo) { función rutaRequire(rutarelativa){ return require(módulos[módulo].dependientes[rutarelativa]) } exportaciones constantes = {}; (función(requerir,exportaciones,código){ evaluación (código) })(rutaRequire,exportaciones,módulos[módulo].código); exportaciones de retorno } requerir('${this.entry}') })(${nuevoCódigo})`; // WebpackBoostrap // Generar archivo. Ponlo en el directorio dist fs.writeFileSync(filePath,bundle,'utf-8') }
Paso 4: Analizar la secuencia de ejecución
Podemos ejecutar el resultado empaquetado en la consola del navegador. Si funciona normalmente, se debe imprimir hola Webpack.
A través del análisis anterior, debemos tener una comprensión básica del proceso general de Webpack. El uso de AST para analizar el código es solo una forma de esta demostración, no la implementación real de Webpack que tiene su propio método de análisis de AST. El ecosistema de Webpack está en constante cambio y los niños interesados pueden considerar las siguientes tres preguntas: