Maison  >  Article  >  interface Web  >  Une analyse approfondie du processus de packaging et des principes du webpack

Une analyse approfondie du processus de packaging et des principes du webpack

青灯夜游
青灯夜游avant
2022-08-09 17:11:163308parcourir

Comment Webpack met-il en œuvre le packaging ? L'article suivant vous donnera une compréhension approfondie des principes d'empaquetage de Webpack. J'espère qu'il vous sera utile !

Une analyse approfondie du processus de packaging et des principes du webpack

En tant que "lion de siège" front-end, Webpack n'est que trop familier. Il peut faire trop de choses. Il peut empaqueter toutes les ressources (y compris JS, TS, JSX, images, polices, CSS, etc.). Le placer dans une relation de dépendance vous permet de référencer des dépendances pour utiliser les ressources selon les besoins. Webpack a fait un excellent travail en traduisant diverses ressources de fichiers sur le front-end et en analysant les dépendances de modules complexes. Nous pouvons également personnaliser le chargeur et charger nos propres ressources librement. Alors, comment Webpack implémente-t-il le packaging ? Venez jeter un oeil aujourd'hui.

Si nous voulons connaître les principes du packaging Webpack, nous devons connaître deux points de connaissances à l'avance

1.

Quand il s'agit de require, la première chose qui vient à l'esprit peut être import. Import est une norme de syntaxe d'es6

– require est un appel d'exécution, donc require peut théoriquement être utilisé n'importe où dans le code ; – import est un appel au moment de la compilation. , il doit donc être placé au début du fichier ;

Lorsque nous utiliserons Webpack pour compiler, nous utiliserons babel pour traduire import en require ; (), qui est utilisé pour charger les modules AMD et CMD. Utilisez également la méthode require pour faire référence.

Par exemple :

var add = require('./a.js');
add(1,2)

Pour faire simple, require est en fait une fonction, et le

référencé n'est qu'un paramètre de la fonction.

./a.js

2. Que sont les exportations ?

Ici, nous pouvons considérer les exportations comme un objet,

Exportation MDN

Vous pouvez voir l'utilisation spécifique. Maintenant que nous comprenons les exigences et les exportations, nous pouvons commencer à emballer.

Jetons d'abord un coup d'œil à la structure du code après notre emballage. Nous pouvons constater que les exigences et les exportations apparaîtront après l'emballage.

Tous les navigateurs ne peuvent pas exécuter require exports. Vous devez implémenter require et exports vous-même pour assurer le fonctionnement normal du code. Le code packagé est une fonction auto-exécutable. Les paramètres ont des informations de dépendance et le code du fichier. Le corps de la fonction exécutée exécute le code via eval.

Une analyse approfondie du processus de packaging et des principes du webpackLe schéma de conception global est le suivant :

Une analyse approfondie du processus de packaging et des principes du webpack

Étape 1 : Écrivez notre fichier de configurationLe fichier de configuration configure notre entrée d'entrée packagée et notre sortie de sortie packagée pour la génération suivante. Les documents sont prêts.

const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "./dist"),//打包后输出的文件地址,需要绝对路径因此需要path
    filename:"main.js"
  },
  mode:"development"

Deuxième étape : analyse du module

Idée générale

: Cela peut se résumer à l'utilisation du fichier fs pour lire le fichier d'entrée et obtenir le chemin du fichier dépendant de l'importation via AST Si le fichier dépendant. a toujours des dépendances, Recurse jusqu'à ce que l'analyse des dépendances soit claire et maintenue dans une carte.

Démontage détaillé

 : Certaines personnes peuvent se demander pourquoi AST est utilisé car AST est né avec cette fonction. Sa ImportDeclaration peut nous aider à filtrer rapidement la syntaxe d'importation. Bien sûr, il est également possible d'utiliser une correspondance régulière. le fichier ne contient qu'un seul caractère après l'avoir lu. String, obtenez le chemin de dépendance du fichier en écrivant des expressions régulières géniales, mais ce n'est pas assez élégant.

étape 1 : Créez de nouvelles dépendances index.js, a.js, b.js comme suit

fichier index.js

import { str } from "./a.js";
console.log(`${str} Webpack`)

fichier a.js

import { b} from "./b.js"
export const str = "hello"

fichier b.js

export const b="bbb"

étape 2 : écrire le Webpack

Analyse de module

 : utilisez @babel/parser d'AST pour convertir la chaîne lue à partir du fichier en une arborescence AST, @babel/traverse pour l'analyse syntaxique et utilisez ImportDeclaration pour filtrer l'importation afin de connaître les dépendances du fichier.

    const content = fs.readFileSync(entryFile, "utf-8");
    const ast = parser.parse(content, { sourceType: "module" });
  
    const dirname = path.dirname(entryFile);
    const dependents = {};
    traverse(ast, {
      ImportDeclaration({ node }) {
        // 过滤出import
        const newPathName = "./" + path.join(dirname, node.source.value);
        dependents[node.source.value] = newPathName;
      }
    })
    const { code } = transformFromAst(ast, null, {
      presets: ["@babel/preset-env"]
    })
    return {
      entryFile,
      dependents,
      code
    }
Les résultats sont les suivants :

Une analyse approfondie du processus de packaging et des principes du webpackUtilisez la récursion ou la boucle pour importer les fichiers un par un pour l'analyse des dépendances. Notez ici que nous utilisons la boucle for pour analyser toutes les dépendances. La raison pour laquelle les boucles peuvent analyser toutes les dépendances. faites attention à la longueur des modules. Cela change. Lorsqu'il y a de nouvelles dépendances dependencies.modules.push, modules.length changera.

 for (let i = 0; i <p></p><p>Étape 3 : Écrire la fonction WebpackBootstrap + générer le fichier de sortie<strong><span style="font-size: 18px;"></span><p><strong>编写</strong> <strong>WebpackBootstrap</strong> <strong>函数</strong>:这里我们需要做的首先是 WebpackBootstrap 函数,编译后我们源代码的 import 会被解析成 require 浏览器既然不认识 require ,那我们就先声明它,毕竟 require 就是一个方法,在编写函数的时候还需要注意的是作用域隔离,防止变量污染。我们代码中 exports 也需要我们声明一下,保证代码在执行的时候 exports 已经存在。</p>
<p><strong>生成输出文件</strong>:生成文件的地址我们在配置文件已经写好了,再用 fs.writeFileSync 写入到输出文件夹即可。</p>
<pre class="brush:php;toolbar:false">  file(code) {
    const filePath = path.join(this.output.path, this.output.filename)
    const newCode = JSON.stringify(code);
    // 生成bundle文件内容
    const bundle = `(function(modules){
      function require(module){
        function pathRequire(relativePath){
          return require(modules[module].dependents[relativePath])
        }
        const exports={};
        (function(require,exports,code){
          eval(code)
        })(pathRequire,exports,modules[module].code);
        return exports
      }
      require('${this.entry}')
    })(${newCode})`;
      //  WebpackBoostrap
    // 生成文件。放入dist 目录
    fs.writeFileSync(filePath,bundle,'utf-8')
  }

Une analyse approfondie du processus de packaging et des principes du webpack

第四步:分析执行顺序

Une analyse approfondie du processus de packaging et des principes du webpack

我们可以在浏览器的控制台运行一下打包后的结果,如果能正常应该会打印出 hello Webpack。

Une analyse approfondie du processus de packaging et des principes du webpack

总结

通过以上的分析,我们应该对 Webpack 的大概流程有基本的了解,利用 AST 去解析代码只是本次演示的一种方式,不是 Webpack 的真实实现,Webpack 他自己有自己的 AST 解析方式,万变不离其宗都是拿到模块依赖,Webpack 生态是很完整,有兴趣的童鞋可以考虑以下三个问题:

  • 如果出现组件循环引用那又应该如何处理?
  • Webpack 是如何加载 loader 的?
  • 犹大大极力推荐的 vite 可以实现按需打包,大大提升开发时候打包速度,如果是 webapck 又是应该如何实现?

更多编程相关知识,请访问:编程视频!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer