最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • webpack源码分析:打包规范

    正文概述 掘金(JeanZhao)   2021-02-26   869

    1. webpack简介

          webpack是当下最热门的前端资源模块化管理和打包工具。简单来说,通过指定入口文件,按照依赖和规则,将许多松散的模块打包成符合环境部署的前端资源。

         通过加载器(loader)、插件(plugin),webpack可以将任何形式的资源,比如 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片、JSON、Coffeescript、LESS 等,转译成模块进行解析。

    webpack源码分析:打包规范     

          面对工程中成百上千个模块,webpack究竟是如何将它们有序地组织在一起,并按照我们预想的顺序运行在浏览器上的呢?

    接下来让我们带着这些问题来开始。首先模块之间是有依赖的,webpack是怎么有序组织起来的呢?

    2. webpack如何处理模块依赖

          这里我就不赘叙了,直接上干货图理解(笔者呕心沥血花了近一周时间,边看源码边整理出来的,该源码版本为:webpack v5.21.1, webpack v4.5.0。后面版本迭代,部分函数名可能会有变动,但主流程思路和逻辑应该是不变的)。简单来说,webpack是利用compiler来控制整个编译流程,Compilation来专门编译构建,最后转交给compiler将文件打包输出到指定目录。

    webpack源码分析:打包规范

    其中处理模块依赖的,主要是由Compilation addModuleTree触发,调用模块工厂ModuleFactory来完成解析。接下来,我们着重来看下它的编译打包部分。

    3. 不同模块方法的打包及源码解析

    首先我们打包一个amd规范的文件示例来看下。(所有示例代码均可在这里找到)

    准备一个最简单的js文件

    // src/index.js
    const logA = () =>console.log('hello webpack');export default logA;
    

    修改webpack配置文件的入口为src/index.js

    // webpack.config.js
    ...
    entry: "./src/index.js",
    ...
    

    修改webpack配置文件的打包方式为amd,

    // webpack.prod.config.js  output: {    path: path.resolve(__dirname, "../dist"),    filename: 'amd.js',    library: "myDemo",    libraryTarget: 'amd'  },
    
    // 打包生成的文件: 打包内容,最外层封装不同define("myDemo", [], (() => (() => {
        "use strict";
        var e = {
            352 : (e, r, o) = >{
                o.r(r),
                o.d(r, {
                default:
                    () = >t
                });
                const t = function() {
                    return console.log("hello webpack")
                }
            }
        },
        r = {};
        function o(t) {
            if (r[t]) return r[t].exports;
            var n = r[t] = {
                exports: {}
            };
            return e[t](n, n.exports, o),
            n.exports
        }
        return o.d = (e, r) =>{
            for (var t in r) o.o(r, t) && !o.o(e, t) && Object.defineProperty(e, t, {
                enumerable: !0,
                get: r[t]
            })
        },
        o.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r),
        o.r = e => {
            "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
                value: "Module"
            }),
            Object.defineProperty(e, "__esModule", {
                value: !0
            })
        },
        o(352)
    })()));
    

    我们可以看到,设置不同的打包规范,最终webpack打包出来的文件模式都很固定模式。

    再对照前面 工作机制的梳理图,compilation.seal调用后(也就是模块构建完成后),会调用create ChunkAssets(实际核心是调用template)将这些模块重组成js代码。

    createChunkAssets(callback) {
       //...
       asyncLib.forEach(            this.chunks,            (chunk, callback) => {
                   let manifest = this.getRenderManifest({...}) // 获取渲染列表               //...               asyncLib.forEach(                    manifest,                    (fileManifest, callback) => {
                           //...
    
                           let source = fileManifest.render(); // 开始渲染                       //...
                           this.emitAsset(file, source, assetInfo);  // 打包文件并输出到指定目录                       //...
                         
                        },
                   callback);
                 }, 
                 callback);}
    

    调用了fileManifest的render函数,其实就是mainTemplate。mainTemplate转交给template去处理,即调用Template.renderChunkModules,并返回了一个ConcatSource的资源。其中有固定的模板,也有调用的模块。

    static renderChunkModules(renderContext, modules, renderModule, prefix = "") {
       // 1. 初始化source
        var source = new ConcatSource();
    
       // 2. 处理模块依赖更新allModules source,并渲染模块    const allModules = modules.map(module => {          return {                id: chunkGraph.getModuleId(module),                source: renderModule(module) || "false"            };     });
        // 3. 模板渲染source,这里简化显示
        source.add("{\n");    for (let i = 0; i < allModules.length; i++) {        const module = allModules[i];        if (i !== 0) {            source.add(",\n");        }        source.add(`\n/***/ ${JSON.stringify(module.id)}:\n`);        source.add(module.source);    }    source.add(`\n\n${prefix}}`);    return source; }
    

    模块工厂(ModuleFactory)给module配备了generator, 生成替换代码。在generate阶段的时候,会触发请求RuntimeTemplate,用于替换运行时的代码。详情请参考该具体编译流程(原链接在这里)

    webpack源码分析:打包规范

    最后通过emitAssets输出到指定目录中文件中去。

    4. 总结

    嗯,其实webpack做的事情很多,源码也很绕,阅读得花费些功夫...初步了解大致工作流程后,下一阶段着重看下loader及plugin的调用处理模块之间依赖的部分。待续。。。(我先去喝杯茶,喘口气儿)

    文中所提的代码规范示例仓库:github.com/JeanZhao/we…


    起源地下载网 » webpack源码分析:打包规范

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元