wepack是什么

面向过程编写的代码非常庞大,难以维护
面向对象编程能提高代码的可维护性,但是会诞生另一个问题,模块太多引起的上线文件过大
而webpack模块打包工具就能解决这一问题,将模块化进行一个大包,极大地优化了项目的大小,对项目上线运行速度有极大地提升

merge

  • 公共配置
  • production配置
  • development配置

merge的作用就是将生产配置和开发配置合并到公共配置中去

核心概念

JavaScript 的 模块打包工具 (module bundler)。通过分析模块之间的依赖,最终将所有模块打包成一份或者多份代码包 (bundler),供 HTML 直接引用。实质上,Webpack 仅仅提供了 打包功能 和一套 文件处理机制,然后通过生态中的各种 Loader 和 Plugin 对代码进行预编译和打包。因此 Webpack 具有高度的可拓展性,能更好的发挥社区生态的力量。

  • mode:
    • development:不压缩代码
    • production:压缩代码
  • Entry: 入口文件,Webpack 会从该文件开始进行分析与编译;
  • Output: 出口路径,打包后创建 bundler 的文件路径以及文件名;
  • Module: 模块,在 Webpack 中任何文件都可以作为一个模块,会根据配置的不同的 Loader 进行加载和打包;
  • Chunk: 代码块,可以根据配置,将所有模块代码合并成一个或多个代码块,以便按需加载,提高性能;
  • Loader: 模块加载器,进行各种文件类型的加载与转换;
  • Plugin: 拓展插件,可以通过 Webpack 相应的事件钩子,介入到打包过程中的任意环节,从而对代码按需修改;

    工作流程 (加载 - 编译 - 输出)

  • 1、读取配置文件webpack.config.js,按命令 初始化 配置参数,创建 Compiler 对象;

  • 2、调用插件的 apply 方法 挂载插件 监听,然后从入口文件开始执行编译;
  • 3、按文件类型,调用相应的 Loader 对模块进行 编译,并在合适的时机点触发对应的事件,调用 Plugin 执行,最后再根据模块 依赖查找 到所依赖的模块,递归执行第三步;
  • 4、将编译后的所有代码包装成一个个代码块 (Chuck), 并按依赖和配置确定 输出内容。这个步骤,仍然可以通过 Plugin 进行文件的修改;
  • 5、最后,根据 Output 把文件内容一一写入到指定的文件夹中,完成整个过程;

    基础配置

    mode 模式

"production" | "development" | "none"
不同的模式会对 webpack 打包的时候进行一些对应的优化配置。

  1. module.exports = {
  2. mode: 'production'
  3. }

entry 指定打包⼊口⽂文件

有三种不同的形式:string | object | array

一对一:一个入口、一个打包文件

  1. module.exports = {
  2. entry: './src/index.js'
  3. }

多对一:多个入口、一个打包文件

  1. module.exports = {
  2. entry: [
  3. './src/index1.js',
  4. './src/index2.js',
  5. ]
  6. }

多对多:多个入口、多打包文件

  1. module.exports = {
  2. entry: {
  3. 'index1': "./src/index1.js",
  4. 'index2': "./src/index2.js"
  5. }
  6. }

output 打包后的文件位置

  • 可以指定一个固定的文件名称,如果是多入口多出口(entry 为对象),则不能使用单文件出口,需要使用下面的方式
  • 通过 webpack 内置的变量占位符:[name]
  1. module.exports = {
  2. ...,
  3. output: {
  4. path: path.resolve(__dirname, "dist"),
  5. filename: "bundle.js",
  6. filename: "[name].js"
  7. }
  8. }

如果想要把静态资源放入cdn

  1. output: {
  2. publicPath: "http://cdn.com.cn",
  3. filename: "[name].js",
  4. path: path.resolve(__dirname, "dist"),
  5. },

多入口文件时,plugin的配置

针对每一个入口文件生成一个plugin的实例,配置chunks

  1. plugins: [
  2. // new HtmlWebpackPlugin({
  3. // template: path.join(srcPath, 'index.html'),
  4. // filename: 'index.html'
  5. // })
  6. // 多入口 - 生成 index.html
  7. new HtmlWebpackPlugin({
  8. template: path.join(srcPath, 'index.html'),
  9. filename: 'index.html',
  10. // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
  11. chunks: ['index'] // 只引用 index.js
  12. }),
  13. // 多入口 - 生成 other.html
  14. new HtmlWebpackPlugin({
  15. template: path.join(srcPath, 'other.html'),
  16. filename: 'other.html',
  17. chunks: ['other'] // 只引用 other.js
  18. })
  19. ]

loaders

Loaders文档
注意loader是从右往左边加载的

  1. const path = require("path");
  2. module.exports = {
  3. mode: "development",
  4. entry: "./src/index.js",
  5. output: {
  6. filename: "index.js",
  7. path: path.resolve(__dirname, "dist"),
  8. },
  9. module: {
  10. rules: [
  11. {
  12. test: /\.jpg$/,
  13. use: {
  14. loader: "file-loader",
  15. },
  16. },
  17. {
  18. test: /\.vue$/,
  19. use: {
  20. loader: "vue-loader",
  21. },
  22. },
  23. ],
  24. },
  25. };

webpack 碰到不识别的模块的时候,webpack 会在配置的 module 中进行该文件解析规则的查找

  • rules 就是我们为不同类型的文件定义的解析规则对应的 loader,它是一个数组
  • 每一种类型规则通过 test 选项来定义,通过正则进行匹配,通常我们会通过正则的方式来匹配文件后缀类型
  • use 针对匹配到文件类型,调用对应的 loader 进行处理
  • exclude:排除掉哪些文件

use配置

options

  • name: placeholder占位符
    • “[name].[ext]”,保持原名打包输出
    • “[name]_[hash].[ext]”,后面加上hash值
  • outputPath:输出目录

常用loader

  • file-loader: 加载文件资源,如 字体 / 图片 等,具有移动/复制/命名等功能;
  • url-loader: 通常用于加载图片,可以将小图片直接转换为 Date Url,减少请求;
  • babel-loader: 加载 js / jsx 文件, 将 ES6 / ES7 代码转换成 ES5,解决兼容性问题;
  • ts-loader: 加载 ts / tsx 文件,编译 TypeScript;
  • style-loader: 将 css 代码以<style>标签的形式插入到 html 中;
  • css-loader: 分析@importurl(),引用 css 文件与对应的资源;
  • postcss-loader: 用于 css 的兼容性处理,具有众多功能,例如 添加前缀,单位转换 等;
  • less-loader / sass-loader: css预处理器,在 css 中新增了许多语法,提高了开发效率;

    file-loader

    把识别出的资源模块,移动到指定的输出⽬目录,并且返回这个资源在输出目录的地址(字符串)
  1. npm install --save-dev file-loader
  1. rules: [
  2. // ...,
  3. {
  4. test: /\.(png|jpe?g|gif)$/,
  5. use: {
  6. loader: "file-loader",
  7. options: {
  8. // placeholder 占位符 [name] 源资源模块的名称
  9. // [ext] 源资源模块的后缀
  10. name: "[name]_[hash].[ext]",
  11. //打包后的存放位置
  12. outputPath: "./images"
  13. // 打包后文件的 url
  14. publicPath: './images',
  15. }
  16. }
  17. }
  18. ]

url-loader

  • 可以处理理 **file-loader** 所有的事情
  • 但是遇到图片格式的模块,可以选择性的把图片转成 base64 格式的字符串,并打包到 js
  • 对⼩体积的图片⽐较合适,⼤图⽚不合适。
    1. rules: [
    2. ...,
    3. {
    4. test: /\.(png|jpe?g|gif)$/,
    5. use: {
    6. loader: "url-loader",
    7. options: {
    8. // placeholder 占位符 [name] 源资源模块的名称
    9. // [ext] 源资源模块的后缀
    10. name: "[name]_[hash].[ext]",
    11. //打包后的存放位置
    12. outputPath: "./images"
    13. // 打包后文件的 url
    14. publicPath: './images',
    15. // 小于 100 字节转成 base64 格式
    16. limit: 100
    17. }
    18. }
    19. }
    20. ]

    css-/sass/style-loader 注意顺序←

    分析多个css文件,最终合并为一个css文件
    把css-loader得到的文件挂载到html文件的head标签里
  1. use: ["style-loader", "css-loader"],
  1. use: ["style-loader", "css-loader", "sass-loader"],

css模块化打包

避免样式冲突

  1. {
  2. loader: "css-loader",
  3. options: {
  4. importLoaders: 2,
  5. modules: true,
  6. },
  7. },
  1. import style from "./index.scss";
  2. var img = new Image();
  3. img.src = cat;
  4. img.classList.add(style.cat);

hash文件

  1. output: {
  2. filename: 'bundle.[contentHash:8].js', // 打包代码时,加上 hash 戳
  3. path: distPath,
  4. },

编写原则:

  • 单一原则: 每个 Loader 只做一件事;
  • 链式调用: Webpack 会按顺序链式调用每个 Loader;
  • 统一原则: 遵循 Webpack 制定的设计规则和结构,输入与输出均为字符串,各个 Loader 完全独立,即插即用;

    plugins

    是类似于生命周期函数的一个钩子函数,比如整个打包过程之后调用

    常用 plugin

  • CommonsChunkPlugin: 代码分割;

  • ProvidePlugin: 自动加载模块;
  • html-webpack-plugin: 加载 html 文件,并引入 css / js 文件;
  • extract-text-webpack-plugin / mini-css-extract-plugin: 抽离样式,生成 css 文件;
  • optimize-css-assets-webpack-plugin: CSS 代码去重;
  • webpack-bundle-analyzer: 代码分析;
  • compression-webpack-plugin: 使用 gzip 压缩 js 和 css;
  • happypack: 使用多进程,加速代码构建;

    HtmlWebpackPlugin

    在打包结束后,⾃动生成⼀个 html ⽂文件,并把打包生成的 js 模块引⼊到该 html
  1. // webpack.config.js
  2. const HtmlWebpackPlugin = require("html-webpack-plugin");
  3. module.exports = {
  4. ...
  5. plugins: [
  6. new HtmlWebpackPlugin({
  7. title: "My App",
  8. filename: "app.html", // 输出的html文件名
  9. template: "./src/html/index.html"
  10. })
  11. ]
  12. };

html 模板中,可以通过 <%=htmlWebpackPlugin.options.XXX%> 的方式获取配置的值

clean-webpack-plugin

自动清理上一次的构建目录

MiniCssExtractPlugin抽离压缩css文件

一般在生产环境使用

配置loader

  1. {
  2. test: /\.scss$/,
  3. loader: [
  4. MiniCssExtractPlugin.loader, // 注意,这里不再用 style-loader
  5. 'css-loader',
  6. 'sass-loader',
  7. 'postcss-loader'
  8. ]
  9. }
  1. // 抽离 css 文件
  2. new MiniCssExtractPlugin({
  3. filename: 'css/main.[contentHash:8].css'
  4. })

sourcemap

是一个映射关系
https://www.webpackjs.com/configuration/devtool/

  • inline-source-map:将.map文件合并到打包文件中去
  • cheap-module-eval-source-map用于开发环境
  • cheap-module-source-map用于生产环境)

WebpackDevServer提升开发效率

webpack-cli中已经自带serve了
使用webpack serve命令即可