工程化进阶之模块编译——优化编译

225 阅读4分钟

前言

正常的构建环节

stateDiagram-v2
[*] --> 构建
构建 --> develop
构建 --> build

develop --> 分析
build --> 分析
分析 --> 优化
优化  --> publish
publish --> deploy
deploy --> [*]

一直想尝试写一篇完成项目部署,从搭建到部署,到构建,到性能分析, 再到优化处理。 此次避开框架脚手架等工具,依托webpack工具直接完成项目编译方面的处理

搭建

工具

  • node(此次使用v12.18.3)及基础依赖工具
  • webpack(此次使用v4.40.2)、webpack-merge(用于提取环境编辑配置)
  • webpack-bundle-analyzer
  • copy-webpack-plugin
  • html-webpack-tags-plugin

假定

假定现在你已经完成前置的项目初始化构建,包括npm注入,git仓库的指定,以及项目『vuereact』的本地启动和初始化编译,最起码的你完成了这些框架脚手架初始化搭建。

那么现在你的项目中会依赖上很多三方库或者工具,比如Vue、React、jQuery、loadash、echart等,你会发现你再build过程中会花费不止两分钟,然后编译处一个2、3M左右的巨物,悲催的开始,这边你就会想着如何去处理这个过程。。。

编译分析

场景一、冷[0]处理

  • 终端编译效果

image.png

  • analysis分析脚本依赖

image.png

分析: 可见几个项目打的模块(库)直接影响到项目构建Size, element-ui、jQuery

场景二、webpack externals提取

由于三方库的引入使得我们构建体积巨大,我们第一反应就是替换,不编译,提取。

  • webpack externals提取公用库
externals: {
    vue: 'Vue',
    jquery: 'jQuery',
    'element-ui': 'ELEMENT',
    xxxxxx
},
  • 终端编译效果

image.png

  • analysis分析脚本依赖

image.png

体积明显减少

细节中存在问题,如果不被编辑那就意味着,需要手动注入三方脚本,那么 去webpack-plugin-html对应的html模板中手动注入cdn或者服务器脚本资源。

<body>
    <h1>
        这里都是你想要的
    </h1>
    <div class="showI" id="wrap-vue">
    </div>
    <script type="text/javascript" src="main.bundle.js"></script>
    <script type="text/javascript" src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js">
    </script>
    xxxxxxxxx
    </body>
</html>

场景三、webpack externals提取 + 动态注入三方脚本

我们的理想是讲脚本动态注入到html模板中,而不是手动,这时候我们就想着,如果:讲node_modules包中的三方脚本拉去出来,放在本地服务器,然后构建一个plugin去完成script的动态注入就行了

  • 使用copy-webpack-plugin去将node_modules中需要的模块化脚本clone到本地,与编辑目录同级,方便读取
  • 自定义的插件中需要完成script的url拼接,参照规则[/vender/vue-2.6.12/vue.js]。
  • 规则url去动态注入html中,结合html-webpack-tags-plugin代替,去插入使用
<body>
    <h1>
        这里都是你想要的
    </h1>
    <div class="showI" id="wrap-vue">
    </div>
    <script type="text/javascript" src="/vender/vue-2.6.12/vue.js"></script>
    <script type="text/javascript" src="/vender/jquery-3.6.0/jquery.js"></script>
    <script type="text/javascript" src="/vender/element-ui-2.15.1/index.js"></script>
    <script type="text/javascript" src="main.bundle.js"></script>
    xxxxxxxxx
    </body>
</html>

:期间遇到问题

  1. 更早的公共内容的提取使用html-webpack-external-plugin,但是于三年前停止维护,现在使用html-webpack-tags-plugin代替;

  2. 由于webpack版本及相关依赖插件比如html-webpack-plugin的版本依赖关系,可能会影响到打包错误显示,或者说程序运行的引用使用方式等问题;

  3. 技巧:如何确认依赖间版本关联

    • 使用脚手架、无论是webpack-cli、或是@vue/cli在或者react-cli,也都一样他们相对成熟些,已经确认的比较体系化的版本依赖,可以相对放心。
    • 确定一个固定依赖项,比如一切依赖基于webpack,其他依赖项都基于这个相关版本升级确认,可进入node_modules查询等方式确认
  4. 这个使用的是copy-webpack-plugin + html-webpack-tags-plugin,其实可以使用add-asset-html-webpack-plugin

html-webpack-tags-plugin不会复制文件,而add-asset-html-webpack-plugin会将文件先复制到dist目录下(当然,可以配置到dist的那个目录),再添加一个标签。

也就是说add-asset-html-webpack-plugin相当于 html-webpack-tags-plugin再加上一个copy-webpack-plugin!


总结

此篇相对简单些,主要介绍,对于前端工程编译的优化方面的处理,结合webpack及插件使用,来完成大型三方库的提取。 借助webpack-bundle-analysis分析,其实不单externals可以对公共模块的提取,业界还有比如说,通过plugin:new webpack.optimize.CommonChunkPlugin,对模块分割,拆分业务模块及vendors。 后期有机会会介绍使用new webpack.optimize.CommonsChunkPlugin()

可考虑优化的方向:

  • webpack版本升级
  • 去掉不必要的插件
  • 代码压缩、代码分割
  • 公共库提取
  • 设置缓存
  • 结合使用版本新特性比如three-loader

推荐一下

Github地址

To Github