# 钩子

const {
    SyncHook,//同步串行钩子 不关系函数的返回值
    SyncBailHook,//同步串行钩子 上一个返回值不为null 跳过剩下的逻辑
    SyncWaterfallHook,//同步串行 上一个监听函数的返回值可以传递给下一个函数
    SyncLoopHook,//同步循环 如果这个函数返回true反复执行 undefined退出
    AsyncParallelHook,//异步并发 不关心每个返回值
    AsyncParallelBailHook,//异步兵法 上一个返回值不为null 跳过剩下的逻辑
    AsyncSeriesHook,//异步串行 不关系callback的参数
    AsyncSeriesBailHook,//callback的参数不为null
    AsyncSeriesWaterfallHook //异步串行上一个监听函数的返回值可以传递给下一个函数
 } = require("tapable");
1
2
3
4
5
6
7
8
9
10
11

https://alienzhou.github.io/webpack-internal-plugin-relation/ avatar

# dist文件分析

npm run dev 打包出dist 文件 main.js整理

(function (modules) {
    // webpack文件进行缓存
    var installedModules = {};
    function __webpack_require__(moduleId) {
        // 判断缓存情况
        if (installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        var module = installedModules[moduleId] = {
            exports: {}
        };
        // 执行key对应的匿名函数
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        return module.exports;
    }
    // Load entry module and return exports
    // 执行入口函数 把export导出
    return __webpack_require__("./src/index.js");
})
    ({
        "./src/index.js": (function (module, exports) {
            console.log('🍎🍎🍎xiaoming!');
        })
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

实现了common.js规范,不发网络请求,把包打包到了自己身上 eval编译快执行快

新建src/data.js

//data.js
const data = 'webpack源码分析';
export default data;

//index.js
import data from './data';
console.log(data);
console.log('🍎🍎🍎xiaoming!');
1
2
3
4
5
6
7
8
//抽离出的main.js
(function (modules) {
    // webpack文件进行缓存
    var installedModules = {};
    function __webpack_require__(moduleId) {
        // 判断缓存情况
        if (installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        var module = installedModules[moduleId] = {
            exports: {}
        };
        // 执行key对应的匿名函数
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        return module.exports;
    }
    // Load entry module and return exports
    // 执行入口函数 把export导出
    return __webpack_require__("./src/index.js");
})
    ({
        //__webpack_require__ => module.exports
        "./src/data.js": (function (module, __webpack_exports__, __webpack_require__) {
            const data = 'webpack源码分析';
            /*
                module.exports = {
                    default:data
                }
            */
            __webpack_exports__["default"] = (data);
        }),
        "./src/index.js": (function (module, __webpack_exports__, __webpack_require__) {
            var _data__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/data.js");
            console.log(_data__WEBPACK_IMPORTED_MODULE_0__["default"]);
            console.log('🍎🍎🍎xiaoming!');
        })
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 与webpack5对比

mkdir webpack5Demo npm install webpack@next --save npm install webpack-cli --save

发现打包出来的dist/main.js 与我们上面删减版本差不多 体积减少了很多

# 异步操作下dist

src/async1.js

const async1 = 'webpack源码分析async1';
export default async1;
1
2

src/data.js

const data = 'webpack源码分析data';
export default data;
1
2

src/index.js

import('./async1').then(res=>{
    console.log(res);
})

import('./data').then(res=>{
    console.log(res);
})
console.log('🍎🍎🍎xiaoming!');
1
2
3
4
5
6
7
8

avatar

dist/main.js下面多了webpackJsonpCallback操作

存在问题 async1.js ---> dist/0.js data.js ---> dist/1.js

// import('./async1').then(res=>{
//     console.log(res);
// })

import('./data').then(res=>{
    console.log(res);
})
console.log('🍎🍎🍎xiaoming!');
1
2
3
4
5
6
7
8

data.js ---> dist/0.js 这样如果我们之前缓存了0.js 那么就需要用户重新再访问然后才能进行缓存

webpack5已经解决了这个问题 开发环境 dist打包出来用文件名称 dist/async__xxxxx.js 生产环境 dist打包出来用hash dist/854.js

webpack4解决方法 魔法注释

import(/*webpackChunkName*/'./data').then(res=>{
    console.log(res);
})
1
2
3

# 实现一个简单webpack

const data = require("./data.js");
console.log(data);
console.log('hello world 😊xianming!');
1
2
3
const fs = require("fs");
let input = "./index.js";
let output = "./dist/index.js";
const ejs = require("ejs");
const getEntry = fs.readFileSync(input, "utf-8");
//后面的文件依赖
let contAry = [];
const dealEntry = getEntry.replace(/(require)\(['"](.+?)["']\)/g, ($1, $2, $3, $4) => {
    let cont = fs.readFileSync($3, "utf-8");
    contAry.push(cont);
    // console.log($2)
    return $2 = `__webpack_require__(${contAry.length})`
})
let template = `
 (function (modules) {
     // 对webpack文件进行缓存
     var installedModules = {};
     function __webpack_require__(moduleId) {
         //判断缓存情况
         if (installedModules[moduleId]) {
             return installedModules[moduleId].exports;
         }
         var module = installedModules[moduleId] = {
             exports: {}
         };
         //执行key对应的匿名函数
         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
         // Return the exports of the module
         return module.exports;
     }
     //执行我们的入口函数 把export导出
     return __webpack_require__(0);
 })([
    (function (module, exports,__webpack_require__) {
        <%- dealEntry %>
    })
    <% for(var i=0;i<contAry.length;i++){ %>
        (function (module, exports) {
            <%- contAry[i] %>
        })
    <% } %>   
 ]);`

let result = ejs.render(template, {
    dealEntry,
    contAry
})
fs.writeFileSync(output, result);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48