Giter Club home page Giter Club logo

webpack-hand-write's Introduction

Webpack Hand-written

webpack-cli

个人理解

webpack-cli 既可以通过 cli 命令行,也可通过脚本形式调用 webpack 进行工程编译。

流程

  • 引入 webpack 核心方法(webpack 本质就是一个方法)
  • 引入 config 文件,获取 options(开发者自定义提供)
  • 执行 webpack(options),返回 compiler 编译器,就是 Compiler 的类实例
  • 执行 compiler.run(callback),传入接收 err, stats 两个参数
  • callback 内部打印出编译成功后的 stats 信息,可选。

实现

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

const compiler = webpack(options);
compiler.run((err, stats) => {
    console.log(err);
    const json = stats.toJson({
        entrypoints: true,
        chunks: true,
        modules: true, // 数组模式
        _modules: true, // 对象方式
        assets: true,
    });
    console.log(JSON.stringify(json, null, 2));
})

webpack

个人理解

webpack 本质是一个函数,函数签名为,接收一个 options 参数,这个参数是开发者提供的,用于自定义自己的编译构建流程;返回值是一个 Compiler 类实例,上面挂在多个编译构建流会用到的 hooks,继承自 Tapable

大概流程

  • 合并配置文件,webpack 中存在三种方式定义的 options,分别是:
    • 开发者定义的 webpack.config.js
    • cli 命令行传入的参数
    • webpack 内部定义的默认配置
  • 初始化配置中的 context 上下文,就是当前执行的根目录(是一个绝对路径)
  • NodeEnvironmentPlugin Node 环境插件,准备 apply 实例方法,接受 compiler ,为 compiler 增加 inputFileSystemoutputFileSystem 的读写操作功能(就是 fs-File-System)
    • fs 是写入硬盘中的
    • 热更新webpack-dev-server 用到的是 memory-fs,读写操作在内存中
  • 挂载配置文件提供的 plugins,迭代调用 plugin.apply 传入 compiler
  • 返回 compiler 实例

webpack plugin

个人理解

webpack 内部提供了多个插件,用于增强 compiler 的功能,同时允许开发者构建自己的插件,集成 webpack ,都遵循下面的特性:

  • 每个插件都是一个 class 类
  • 提供 apply 实例方法,接收 compiler,在这个方法内部为 compiler 增强功能

下面会一一谈到 webpack 内置的插件。

NodeEnvironmentPlugin

NodeEnvironmentPlugin 为 compiler 增加读写功能

const fs = require('fs');

class NodeEnvironmentPlugin {
    constructor(options) {
        this.options = options || {};
    }
    apply(compiler) {
        compiler.inputFileSystem = fs;
        compiler.outputFileSystem = fs;
    }
}

module.exports = NodeEnvironmentPlugin;

WebpackOptionsApply

提供 process 方法,内部统一挂载 webpack 内置的插件

const EntryOptionPlugin = require('./EntryOptionPlugin');

class WebpackOptionsApply {
    process(options, compiler) {
        new EntryOptionPlugin().apply(compiler);
    }
}

module.exports = WebpackOptionsApply;

EntryOptionPlugin

内部监听了 entryOptions 钩子函数,执行回调内部,新建 SingleEntryPlugin 实 例

const SingleEntryPlugin = require("./SingleEntryPlugin");

class EntryOptionPlugin{
    apply(compiler) {
        // 当有一个 entryOption 事件钩子触发时,执行回调,传入 context 和 entry
        compiler.hooks.entryOptions.tap('EntryOptionPlugin', (context, entry) => {
            // 创建 SingleEntryPlugin
            new SingleEntryPlugin(context, entry, 'main').apply(compiler);
        })
    }
}

module.exports = EntryOptionPlugin;

SingleEntryPlugin

内部监听 make 事件,这个插件比较重要,compiler.compiler 启动编译时,会触发这个 make 监听的钩子函数

class SingleEntryPlugin {
    /**
     * 
     * @param {*} context 根目录 绝对路径
     * @param {*} entry 入口文件 index.js
     * @param {*} name 入口 别名 main
     */
    constructor(context, entry, name) {
        this.context = context;
        this.entry = entry;
        this.name = name;
    }

    apply(compiler) {
        // 监听 make 事件
        compiler.hooks.make.tapAsync('SingleEntryPlugin', (compilation, callback) => {
            console.log(callback);
            // callback 表示一个钩子函数完成了(内部计数器),等所有注册的钩子函数结束后,才会执行
            console.log('开始编译入口', this.entry);
            // 开始真正编译入口 entry
            // compilation.addEntry(this.context, this.entry, this.name, callback);
        })
    }
}

module.exports = SingleEntryPlugin;

下面是 compiler.compile 内部触发的部分代码

this.hooks.compile.call(params);
let compilation = this.newCompilation(params);
// make 让所有的入口同时开始编译,全部编译后才执行 omCompiled
// 第二参数是一个函数,被称为最终的回调
this.hooks.make.callAsync(compilation, err => { // make 成功后的回调
    // 凡是注册了 make 钩子的函数全部成功了,才会触发这个回调 callback
    // 类似:Promise.resolve().then(err => {})
    onCompiled(err, compilation);
})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.