webpack4-学习笔记(进阶篇)

287 阅读7分钟

进阶篇

以⼯程化的⽅式组织 webpack 构建配置,和 webpack 打包优化

一、编写可维护的 webpack 构建配置

构建配置抽离成 npm 包的意义

通用性

  • 业务开发者无需关注构建配置

  • 统一团队构建脚本

可维护性

  • 构建配置合理的拆分

  • README 文档、ChangeLog 文档等

质量

  • 冒烟测试、单元测试、测试覆盖率

  • 持续集成

构建配置管理的可选方案

通过多个配置文件管理不同环境的构建,webpack --config 参数进行控制

将构建配置设计成一个库,比如:hjs-webpack、Neutrino、webpack-blocks

抽成一个工具进行管理,比如:create-react-app, kyt, nwb

将所有的配置放在一个文件,通过 --env 参数控制分支选择

构建配置包设计

通过多个配置文件管理不同环境的 webpack 配置

  • 基础配置:webpack.base.js

  • 开发环境:webpack.dev.js

  • 生产环境:webpack.prod.js

  • SSR环境:webpack.ssr.js

抽离成一个 npm 包统一管理

  • 规范:Git commit日志、README、ESLint 规范、Semver 规范

  • 质量:冒烟测试、单元测试、测试覆盖率和 CI

通过 webpack-merge 组合配置

merge = require("webpack-merge")

...

merge(

... { a: [1], b: 5, c: 20 },

... { a: [2], b: 10, d: 421 }

... )

{ a: [ 1, 2 ], b: 10, c: 20, d: 421 }

合并配置:module.exports = merge(baseConfig, devConfig);

功能模块设计

image.png

目录结构设计

+ |- /test   // test 放置测试代码

+ |- /lib    // lib 放置源代码

    + |- webpack.dev.js

    + |- webpack.prod.js

    + |- webpack.ssr.js

    + |- webpack.base.js

+ |- README.md

+ |- CHANGELOG.md

+ |- .eslinrc.js

+ |- package.json

+ |- index.js

使用 ESLint 规范构建脚本

// 使用 eslint-config-airbnb-base
// eslint --fix 可以自动处理空格
module.exports = {

    "parser": "babel-eslint",

    "extends": "airbnb-base",

    "env": {

        "browser": true,

        "node": true

    }

};

冒烟测试 (smoke testing)

冒烟测试是指对提交测试的软件在进行详细深入的测试之前而进行的预测试,这种

预测试的主要目的是暴露导致软件需重新发布的基本功能失效等严重问题。

冒烟测试执行

构建是否成功

每次构建完成 build 目录是否有内容输出

  • 是否有 JS、CSS 等静态资源文件

  • 是否有 HTML 文件

判断构建是否成功

在示例项目里面运行构建,看看是否有报错

image.png

判断基本功能是否正常

编写 mocha 测试用例

  • 是否有 JS、CSS 等静态资源文件

  • 是否有 HTML 文件

1844674407267665357118446744073416735611.jpg

单元测试与测试覆盖率

image.png

编写单元测试用例

image.png

单元测试接入

  1. 安装 mocha + chai

    npm i mocha chai -D

  2. 新建 test 目录,并增加 xxx.test.js 测试文件

  3. 在 package.json 中的 scripts 字段增加 test 命令

    "scripts": {

     "test": "node_modules/mocha/bin/_mocha”
    

    },

  4. 执行测试命令

    npm run test

持续集成的作用

优点:

  • 快速发现错误

  • 防止分支大幅偏离主干

核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。 1844674407210942753918446744072246642118.jpg

Github 最流行的 CI

image.png

接入 Travis CI

  1. travis-ci.org/ 使用 GitHub 账号登录

  2. travis-ci.org/account/rep… 为项目开启

  3. 项目根目录下新增 .travis.yml

travis.yml 文件内容

install 安装项目依赖

script 运行测试用例 184467440720727278791698453907_副本.jpg

发布到 npm

添加用户: npm adduser

升级版本

升级补丁版本号:npm version patch

升级小版本号:npm version minor

升级大版本号:npm version major

发布版本:npm publish

Git 规范和 Changelog 生成

良好的 Git commit 规范优势:

  • 加快 Code Review 的流程

  • 根据 Git Commit 的元数据生成 Changelog

  • 后续维护者可以知道 Feature 被修改的原因

技术方案 21190588192049528181.jpg

提交格式要求

1844674407244481461118446744073340637795.jpg

本地开发阶段增加 precommit 钩子

image.png

Changelog 生成

image.png

开源项目版本信息案例

image.png

遵守 semver 规范的优势

优势:

  • 避免出现循环依赖

  • 依赖冲突减少 1844674407201374477918446744073542935891.jpg

语义化版本(Semantic Versioning)规范格式

主版本号:当你做了不兼容的 API 修改,

次版本号:当你做了向下兼容的功能性新增,

修订号:当你做了向下兼容的问题修正。

先行版本号

先行版本号可以作为发布正式版之前的版本,格式是在修订版本号后面加上一个连接 号(-),再加上一连串以点(.)分割的标识符,标识符可以由英文、数字和连接号 ([0-9A-Za-z-])组成。

  • alpha:是内部测试版,一般不向外部发布,会有很多 Bug。一般只有测试人员使用。

  • beta:也是测试版,这个阶段的版本会一直加入新的功能。在 Alpha 版之后推出

  • rc:Release Candidate) 系统平台上就是发行候选版本。RC 版不会再加入新的功能了,主要着重于除错。

二、webpack 构建速度和体积优化策略

初级分析:使用 webpack 内置的 stats

stats: 构建的统计信息

package.json 中使用 stats

image.png

Node.js 中使用

image.png

速度分析:使用 speed-measure-webpack-plugin

image.png

速度分析插件作用

分析整个打包总耗时

每个插件和loader的耗时情况

webpack-bundle-analyzer 分析体积

image.png

可以分析哪些问题?

依赖的第三方模块文件大小

业务里面的组件代码大小

使用高版本的 webpack 和 Node.js

image.png

使用 webpack4:优化原因

image.png

多进程/多实例构建:资源并行解析可选方案

image.png

多进程/多实例:使用 HappyPack 解析资源

image.png

多进程/多实例:使用 thread-loader 解析资源

image.png

多进程/多实例:并行压缩

方法一:使用 parallel-uglify-plugin 插件

image.png

方法二:uglifyjs-webpack-plugin 开启 parallel 参数

image.png

方法三:terser-webpack-plugin 开启 parallel 参数

image.png

分包:设置 Externals

image.png

进一步分包:预编译资源模块

思路:将 react、react-dom、redux、react-redux基础包和业务基础包打包成一个文件

方法:使用 DLLPlugin 进行分包,DllReferencePlugin对 manifest.jso引用

使用 DLLPlugin 进行分包

image.png

使用 DllReferencePlugin 引用 manifest.json

image.png

缓存

目的:提升二次构建速度

缓存思路:

  • babel-loader 开启缓存

  • terser-webpack-plugin 开启缓存

  • 使用 cache-loader 或者 hard-source-webpack-plugin

缩小构建目标

目的:尽可能的少构建模块

比如 babel-loader 不解析 node_modules

image.png

减少文件搜索范围

image.png

图片压缩

image.png

Imagemin的优点分析

有很多定制选项

可以引入更多第三方优化插件,例如pngquant

可以处理多种图片格式

Imagemin的压缩原理

pngquant: 是一款PNG压缩器,通过将图像转换为具有alpha通道(通常比24/32位PNG文件小60-80%)的更高效的8位PNG格式,可显著减小文件大小。

pngcrush:其主要目的是通过尝试不同的压缩级别和PNG过滤方法来降低PNG IDAT数据流的大小。

optipng:其设计灵感来自于pngcrush。optipng可将图像文件重新压缩为更小尺寸,而不会丢失任何信息。

tinypng:也是将24位png文件转化为更小有索引的8位图片,同时所有非必要的metadata也会被剥离掉

tree shaking(摇树优化)复习

概念:1 个模块可能有多个方法,只要其中的某个方法使用到了,则整个文件都会被打到

bundle 里面去,tree shaking 就是只把用到的方法打入 bundle ,没用到的方法会在uglify 阶段被擦除掉。

使用:webpack 默认支持,在 .babelrc 里设置 modules: false 即可

  • production mode的情况下默认开启

要求:必须是 ES6 的语法,CJS 的方式不支持

无用的 CSS 如何删除掉?

PurifyCSS: 遍历代码,识别已经用到的 CSS class

uncss: HTML 需要通过 jsdom 加载,所有的样式通过PostCSS解析,通过document.querySelector 来识别在 html 文件里面不存在的选择器

在 webpack 中如何使用 PurifyCSS?

使用 purgecss-webpack-plugin

和 mini-css-extract-plugin 配合使用

8909729721267558137.jpg

构建体积优化:动态 Polyfill

image.png

Promise 的浏览器支持情况

image.png

构建体积优化:动态 Polyfill

image.png

Polyfill Service原理

image.png

构建体积优化:如何使用动态 Polyfill service

polyfill.io 官方提供的服务

image.png

基于官方自建 polyfill 服务

//huayang.qq.com/polyfill_service/v2/polyfill.min.js?unknown=polyfill&features=Promise,Map,Set

体积优化策略总结

Scope Hoisting

Tree-shaking

公共资源分离

图片压缩

动态 Polyfill