webpack

1 什么是webpack

构建就是把源代码转换成线上可执行的js、css、html

  • 代码转换ts->js、less->css等

  • 文件优化,压缩js、css、html,合并图片

  • 代码分割,提取多个页面的公共代码,提取首屏不需要执行的代码异步加载,路由按需加载

  • 模块合并

  • 监听本地源代码变化,自动重新构建,刷新浏览器

  • 代码校验,在代码提交到仓库前校验代码,以及单元测试是否通过

  • 自动发布,更新完代码后,自动构建出现上发布代码并传输给发布系统

  • Tree-Shaking

  • 利用CDN加速,在构建过程中,将引用的静态资源路径修改为CDN上对应的路径

2 核心概念

  • entry:入口,可抽象成输入,单入口写成字符串,多入口写成对象

  • output:输出结果,在webpack经过一系列处理并得出最终想要的代码后输出结果,单出口filename和path,多出口使用占位符[name].js

  • loader:模块转换器,用于把原生不支持的模块转换成有效的模块,并添加到依赖图中,原生只支持js和json,其本质是一个函数

    babel-loader

    css-loader

    less-loader

    ts-loader

    file-loader

    raw-loader

    thread-loader

  • plugin:在Webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情,增强webpack功能,作用于整个构建过程,可以简单理解为webpack不能做的事情plugin都可以做

    CommonsChunkPlugin

    CleanWebpackPlugin

    ExractTextWebpackPlugin

    CopyWebpackPlugin

    HtmlWebpackPlugin

    UglifyjsWebpackPlugin

    ZipWebpackPlugin

  • mode: production、development、none

  • module:在webpack里一切皆模块,一个模块(css、font、image)对应着一个文件,webpack会从配置的entry开始递归找出所有依赖的模块

  • chunk:代码块,一个chunk由多个模块组合而成,用于代码合并与分割

3 get started

  1. mkdir webpack-demo

  2. cd webpack-demo

  3. npm init -y

  4. npm i webpack webpack-cli webpack-dev-server(自动打包、监视文件改变、刷新浏览器) -D

  5. 创建和配置webpack.config.js(可以修改名字)

  6. 配置npm scripts

  7. 安装plugin和loader

4 webpack基础

1 resolve es6

  • npm i @babel/core @babel/preset-env babel-loader -D

2 resolve jsx

  • npm i @babel/core babel-loader react react-dom @babel/preset-react -D

  • "@babel/preset-react" in .babelrc

  • webpack.config.js配置babel-loader

3 resolve css and less(sass)

  • npm i style-loader css-loader less less-loader -D`

4 resolve less(sass)

  • npm i less less-loader -D

5 file-loader(resolve img and font)

  • npm i file-loader -D

6 url-loader

7 文件监听

  • package.json启动webpack命令带上--watch(需要手动刷新浏览器)

  • 在配置webpack.config.js中设置watch: true

8 热更新

webpack-dev-server(只能hot组件和css)

  • 不输出文件而是放在内存中

  • 使用HotModuleReplacementPlugin插件

webpack-dev-middleware

  • WDM将webpack输出的文件传输给服务器

  • 适用于灵活定制的场景

9 文件指纹(不能和热更新一起使用)

  • Hash: 和整个项目构建相关,只要项目文件有修改,整个项目构建的hash就会改变

  • Chunkhash: 和webpack打包的chunk有关,不同entry生成不同的chunkhash

  • Contenthash: 根据文件内容定义hash,文件内容不变则Contenthash不变,一般css用这种

10 compress html/css/js

  • webpack4内置uglifyjs-weabpack-plugin

  • optimize-css-assets-webpack-plugin + cssnano压缩CSS文件

  • html-webpack-plugin

11 vue-loader

12 webpack-chunk-name合并包

13 alias

14 公共库放到CDN(webpack-cdn-plugin)

5 webpack进阶

1 clear dist folder

  • 通过npm scripts rm -rf./dist && webpack or rimraf ./dist && webpack

  • clean-webpack-plugin

2 PostCSS插件autoprefixer

  • Trident(-ms)、Geko(-moz)、Webkit(-webkit)、Presto(-o)

  • npm i postcss-loader autoprefixer -D

3 px convert to rem

  • @media

  • npm i px2rem-loader -D

  • npm i lib-flexible -S(动态计算根元素font-size,打开页面时就计算)

  • font-size: 12px; /*no*/ 不进行rem转换

4 资源内联

  • 代码层面

    • 页面框架的初始化脚本

    • 上报相关打点

    • css内联避免页面闪动

  • 请求层面

    • 小图片或字体内联(url-loader)

html/js内联(raw-loader)

css内联

  • html-inline-css-webpack-plugin(推荐)

  • style-loader

5 MPA bundle

6 source map(开发环境启用,线上关闭)

  • eval: 使用eval包括模块代码

  • source map: 产生.map文件

  • cheap: 不包含列信息

  • inline: 将.map作为DataURI嵌入,不单独生成.map

  • module: 包含loader的source map

7 提取公共资源

  • html-webpack-externals-plugin

  • SplitChunksPlugin(代替webpack3的CommonsChunkPlugin)

8 tree shaking(静态分析)

  • 必须是ES6的语法,CJS不支持

  • DCE(代码不可到达,代码执行结果不会被用到,代码只影响死变量(只写不读))

  • 函数必须是纯函数

  • mode:productio/none

  • 原理

    • 只能作为模块顶层的语句出现

    • import的模块名只能是字符串常量

    • import binding是immutable的

    • uglify阶段删除无用代码

9 Scope Hoisting

  • 现象:构建后的代码存在大量闭包

  • 导致问题:大量作用域包裹代码体积变大,运行代码时创建的函数作用域变多,内存开销变大

  • 原理:将所有模块的代码按照所引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突

  • 必须是ES6语法,CJS不支持

  • mode:productio/none

  • webpack3需要使用new webpack.optimize.ModuleConcatenationPlugin()

10 code split and dynamic import

1 意义

  • 抽离相同代码到一个chunk

  • 脚本懒加载,初始化代码更小(比如首屏)

2 方式

  • CJS: require.ensure

  • ES6: 动态import(目前没有原生支持,需要babel转换)

11 webpack integrate eslint

  • eslint-config-airbnb、eslint-config-airbnb-base

  • integrate with CI/CD

  • integrate with webpack

  • precommit hook

12 webpack打包库和基础组建

13 SSR

  • 核心是减少请求

  • 优势

    • 减少白屏时间

    • SEO友好

  • 思路

    • 服务端:使用react-dom/server的renderToString将react组件渲染成字符串,服务端路由返回对应的模版

    • 客户端:打包出针对服务端的组件

  • 常见问题

    • 没有windowdocument, 需要hack

    • 没有fetchajax,改成axiosisomorphic-fetch

    • 无法解析css

      • 服务端通过ignore-loader忽略css解析

      • style-loader换成isomorphic-css-loader

      • 推荐(使用浏览器端的html,设置占位符,动态插入组件和data)

14 构建输出日志

  • stats: 'error-only' //none/mininal/normal/verbose,开发环境设置到devServer里

  • friendly-errors-webpack-plugin(plugins: [new FriendlyErrorsWebpackPlugin()]) + stats: 'error-only'

15 构建异常处理

16 others

  • ProvidePlugin or expose-loader

  • webpack-merge

  • DefinePlugin //配置全局变量

  • PrefetchPlugin

  • webpack-md5-hash

  • webpack-manifest-plugin && assets-webpack-plugin

  • image-webpack-loader

6 some plugins examples

  • delete useless css(webpack3)

  • 抽离style from js to css link文件

  • 抽离css和less到单独文件

  • 解决抽离后css不热更新问题,开发时需要

  • 拷贝静态图片

  • 在html中使用图片

7 魔法注释

8 构建配置包设计

  • 集成ESLint

  • 冒烟测试(是否生成html、css、js)(mocha)

  • 单元测试(mocha+chai)

  • 测试覆盖率istanbul

  • 持续集成TravisCI

  • 发布npm

  • Git commit规范

9 打包优化

分析

  1. stats

  2. speed-measure-webpack-plugin

  3. webpack-bundle-analyzer

优化

速度优化

  1. 多进程/多实例打包

    • thread-loader(thread-loader不可以和 mini-css-extract-plugin 结合使用)

    • HappyPack

  2. 多进程/多实例并行压缩

    • terser-webpack-plugin

    • parallel-uglify-plugin

    • uglifyjs-webpack-plugin

  3. 进一步分包(预编译资源模块)

  4. 缓存(提升二次构建速度)

  • babel-loader

  • teser-webpack-plugin

  • hard-source-webpack-plugin

  1. 缩小构建目标

体积优化

  1. Tree Shaking

    • js(.babelrc设置modules:false, production mode默认开启,必须ES6语法)

    • css

      • purgecss-webpack-plugin + mini-css-exrtract-plugin(webpack4)

      • purgecss-webpack-plugin + extract-text-webpack-plugin(webpack3)

  2. image compress

  3. dynamic Polyfill

  4. 公共资源分离

  5. Scope Hoisting

  6. others

    1. dynamic import component

    2. resolve.noParse(忽略依赖库的解析)

    3. ContextReplacementPlugin or IgnorePlugin

    4. performance参数可以输出文件的性能检查配置

    5. 开发环境下将devtool设置为cheap-module-eval-source-map速度最快加速构建.在生产环境下将其设置为cheap-module-source-map

Last updated