webpack流程深入了解和debugger方式

186 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

1. webpack介绍

webpack 我们常用的打包工具,需要通过webpack.config.js配置来实现js,sass,less,文件等的处理。webpack只能处理js和json,使用loader可以转换非js文件,如sass转成css。plugin是webpack实现一些特殊处理和优化的插件,在webpack的打包流程中,会抛出一些已经监听的事件,plugin内的钩子去处理,改变wepback的打包结果。 以下为常用的webpack loaderplugin

image.png

2. debugger方式介绍

  • 通过执行命令调试
    • 打开工程目录,点击调试按钮,再点击小齿轮的配置按钮系统就会生成 launch.json 配置文件
    • 修改好了以后直接点击 F5 就可以启动调试
{ "version": "0.2.0",
    "configurations": [ 
    { "type": "node", 
    "request": "launch",
    "name": "debug webpack", 
    "cwd": "${workspaceFolder}",
    "program": "${workspaceFolder}/node_modules/webpack-cli/bin/cli.js" } 
    ] 
}
  • 通过 chrome 调试 chrome://inspect node --inspect-brk ./node_modules/webpack-cli/bin/cli.js,然后打开 Chrome 浏览器控制台就可以调试了
image.png

3. webpack打包流程

3.1 引入webpack和webpack.config.js, 调用webpack方法得到compiler,传入options配置,合并shell语句和配置文件的参数,得到最终的配置对象

const webpack = require('webpack');
const configFactory = require('../config/webpack.config');

3.2 用上一步得到的配置参数,初始化Compiler对象

  const compiler = new Compiler(finalOptions);

3.3 加载配置里面的插件, 循环调用plugin的apply方法

  const { plugins } = finalOptions;
  for (let plugin of plugins) {
    plugin.apply(compiler);
  }

3.4 执行Compiler的run方法开始执行编译

compiler.run((err, stats) => {});
// Compiler 类
class Compiler{
  constructor(options) {
    this.options = options;
    this.hooks = {
      run: new SyncHook(),//在开始编译之前调用
      done:new SyncHook() //在编译完成时执行
    }
  }
  run(callback) {
    // 在编译的开始调用开始钩子
    this.hooks.run.call();
    //在编译的过程中会收集所有的依赖的模块或者说文件
    //stats指的是统计信息 modules chunks  files=bundle assets指的是文件名和文件内容的映射关系
    const onCompiled = (err, stats, fileDependencies) => {
        /**  省略部分代码*/
    //在编译完成时触发done钩子执行  
      this.hooks.done.call();
    }
    //调用compile方法进行编译
    this.compile(onCompiled);
  }
  //开启一次新的编译
  compile(callback) {
    //每次编译 都会创建一个新的Compilation实例,
    let compilation = new Compilation(this.options,this);
    //  compilation.build 内部实现: 
    // 读取入口文件
    // 文件根据role匹配来使用对应的loader去处理文件
    // 递归查找依赖,所有文件都经过编译后。组装成包含多个文件的chunk
    // 根据对应关系输出文件列表, 在callback中写入文件
    compilation.build(callback);
  }
}

3.5 在Compiler里面onCompiled处理文件写入和依赖文件的监听, 最后调用完成钩子

 const onCompiled = (err, stats, fileDependencies) => {
      //在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
      for (let filename in stats.assets) {
        let filePath = path.join(this.options.output.path, filename);
        fs.writeFileSync(filePath,stats.assets[filename],'utf8');
      }
      callback(err, { toJson: () => stats });//是这里面传给run方法的回调 compiler.run((err, stats) => {});

      for (let fileDependency of fileDependencies) {
         //监听依赖的文件变化,如果依赖的文件变化后会开始一次新的编译
        fs.watch(fileDependency,()=>this.compile(onCompiled));
      }
      this.hooks.done.call();//在编译完成时触发done钩子执行
    }
    //调用compile方法进行编译
    this.compile(onCompiled);

小结

整体介绍了webpack的debugger方式和打包流程,对webpack有了整体的印象,后面深入学习loader和plugin的使用和实现。