简介

  1. 开发时,我们会使用框架(react、vue),es6模块化语法,less/sass等css预处理器语法进行开发。这样的代码要想在浏览器运行必须经过编译成浏览器能识别的js、css等语法才能运行,所以我们需要打包工具帮我们做完这些事
  2. 除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等

基本使用

  1. Webpack本身功能有限
    • 开发模式:能编译js中的ES Module语法
    • 生产模式:能编译js中的ES Module语法,还能压缩js代码
  2. 基本指令
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 初始化package.json
    npm init -y

    # 下载依赖
    npm i webpack webpack-cli -D

    # 开发模式
    npm webpack ./src/main.js --mode=development

    # 生产模式
    npx webpack ./src/main.js --mode=production

    npx webpack:是用来运行本地安装webpack包的
    ./src/main.js:指定webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来
    –mode=xxx:指定模式(环境)

基本配置

5大核心概念

  1. entry(入口):指示webpack从哪个文件开始打包
  2. output(输出):指示webpack打包万的文件输出到哪里去,如何命名等
  3. loader(加载器):webpack本身只能处理js、json等资源,其他资源需要借助loader,webpack才能解析
  4. plugins(插件):扩展webpack的功能
  5. mode(模式):
    • 开发模式:development
    • 生产模式:production

配置文件

  1. 项目根目录创建webpack.config.js配置文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // nodejs核心模块,专门用来处理路径问题
    const path = require("path");

    module.exports = {
    entry: "./src/main.js",
    output: {
    // __dirname指配置文件的当前位置
    path: path.resolve(__dirname, "dist"),

    // 如果我们在根目录创建config文件夹,并把配置文件丢进去
    // 同时希望dist文件夹生成在根目录,就要../到上一层输出dist文件夹
    // path: path.resolve(__dirname, "../dist"),

    filename: "main.js"
    },
    module: {
    rules: [
    // loader的配置
    ]
    },
    plugins: [],
    mode: "development"
    }
  2. 终端在项目目录中,输入npx webpack指令,就会寻找配置文件并加载里面的配置

开发模式

  1. 编译代码,使浏览器能识别运行
    • 开发时,我们有样式资源、字体图标、图片资源、html资源等,webpack默认都不能处理这些资源,所以我们要加载配置来编译这些资源
  2. 代码质量检查,树立代码规范
    • 提前检查代码的一些隐患,让代码运行时能更加健壮
    • 提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观

处理样式资源

处理css资源

  1. 安装css-loaderstyle-loader,已安装请忽略
    1
    2
    npm install --save-dev css-loader
    npm install --save-dev style-loader
  2. 创建一个css文件,引入到main.js,通常是入口文件
    1
    2
    3
    // 想要webpack打包资源,必须引入该资源
    // 只是用来打包,不需要定义变量接收它
    import "./css/index.css"
  3. 接着到配置文件中,注意use配置中有style-loader,如果只安装css-loader肯定会报错
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module.exports = {
    module: {
    rules: [
    {
    test: /\.css$/, // 只检测.css文件
    use: [
    // 执行顺序,从右到左(从下到上)
    "style-loader", // 将js中的css通过创建style标签添加到html文件
    "css-loader", // 将css资源编译成commonjs模块到js中
    ],
    },
    ],
    },
    };
  4. 输入npx webpack指令,重新加载配置

处理less资源

  1. 安装lessless-loader,已安装请忽略
    1
    npm install less less-loader --save-dev
  2. 创建一个less文件,引入到main.js,通常是入口文件
    1
    2
    3
    // 想要webpack打包资源,必须引入该资源
    // 只是用来打包,不需要定义变量接收它
    import "./less/index.less"
  3. 接着到配置文件中,注意官方文档用的是loader: [...],这种方式只能使用1个loader,所以要改成use,它可以使用多个loader
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    module.exports = {
    module: {
    rules: [
    {
    test: /\.less$/,
    // loader: ['style-loader', 'css-loader', 'less-loader'],
    use: [
    'style-loader',
    'css-loader',
    'less-loader' // 将less编译成css
    ]
    },
    ],
    },
    };
  4. 输入npx webpack指令,重新加载配置

处理sass和scss资源

  1. 安装sasssass-loader,已安装请忽略
    1
    npm install sass-loader sass --save-dev
  2. 创建sass与scss文件,引入到main.js,通常是入口文件
    1
    2
    3
    4
    // 想要webpack打包资源,必须引入该资源
    // 只是用来打包,不需要定义变量接收它
    import "./sass/index.sass"
    import "./sass/index.scss"
  3. 接着到配置文件中,添加sass-loader配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module.exports = {
    module: {
    rules: [
    {
    test: /\.s[ac]ss$/, // 使用[]表示检测.sass或.scss文件
    use: [
    'style-loader',
    'css-loader',
    'sass-loader' // 将sass编译成css
    ]
    },
    ],
    },
    };
  4. 输入npx webpack指令,重新加载配置

处理stylus资源

  1. 国内几乎没什么人用,跳过吧

处理图片资源

  1. 过去在webpack4时,我们处理图片资源通过file-loaderurl-loader进行处理
  2. 现在webpack5已经将两个loader功能内置到webpack里了,只需要简单配置即可处理图片资源
  3. 官方文档搜资源模块,有个处理图片的功能,主要是把图片转成base64(字符串),减少向服务器请求图片的次数,缺点是图片转成base64体积会变大,但我们只处理10kb以下的图片,那么增加个1~2kb,其实也无所谓
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    module: {
    rules: [
    {
    test: /\.(png|jpe?g|gif|webp|svg)$/,
    type: 'asset',
    parser: {
    dataUrlCondition: {
    maxSize: 10 * 1024 // 10kb
    }
    }
    }
    ]
    }

修改输出路径

  1. 有时候,我希望输出的文件,各自在自己的文件夹内,而不是全部挤在一起
  2. 首先是修改js输出路径,它的位置在output内,我们需要修改的是filename,通常只有main.js这个文件
    filename: "static/js/main.js"
  3. 上面提到处理图片资源,但却少了输出路径,我们也加上吧
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    module: {
    rules: [
    {
    test: /\.(png|jpe?g|gif|webp|svg)$/,
    type: 'asset',
    parser: {
    dataUrlCondition: {
    maxSize: 10 * 1024 // 10kb
    }
    },
    generator: {
    // 输出图片的名称
    // hash表示生成的图片名是哈希值,不会重名,10是取10位
    // ext是保留后缀名,比如.jpg等
    // query是保留携带参数
    filename: "static/images/[hash:10][ext][query]"
    }
    }
    ]
    }

自动清空上次打包内容

  1. 每次想看打包效果,总需要提前删除打包好的文件,在输入打包命令,这太麻烦了。于是webpack提供了一个清空参数,原理是打包前,将output整个目录内容清空,再进行打包
    1
    2
    3
    4
    5
    6
    module.exports = {
    //...
    output: {
    clean: true, // 在生成文件之前清空 output 目录
    },
    };

处理字体图标资源

  1. 主要讲阿里巴巴的字体图标,下载后选哪种引入方式,多色字体图标毫无疑问选Symbol,单色字体选哪个都行,使用Font class引入会简单一些,这次选Font class引入。总共需要把4个文件放进项目,iconfont.css放css文件夹内,那三个字体文件放fonts文件夹内,修改下iconfont.css路径问题
  2. 别忘了把iconfont.css导入到main.js😉
  3. 字体图标配置和处理图片资源差不多,但我们不需要转换base64,所以要改成asset/resource,它会原封不动把字体图标输出出去。当然,输出路径我们也需要,修改成media可以了,这是视频的意思,下面会解释
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    module: {
    rules: [
    {
    test: /\.(ttf|woff2?)$/,
    type: 'asset/resource', // 不需要转换base64
    generator: {
    filename: "static/media/[hash:10][ext][query]"
    }
    }
    ]
    }

处理其他资源

  1. 考虑到未来会增加很多资源,每个资源都进行分类,那太麻烦了,不如统一丢到media文件夹内,我们需要做的只是添加后缀名
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    module: {
    rules: [
    {
    test: /\.(ttf|woff2?|mp[34]|avi)$/,
    type: 'asset/resource', // 不需要转换base64
    generator: {
    filename: "static/fonts/[hash:10][ext][query]"
    }
    }
    ]
    }

处理js资源

webpack对js处理是有限的,只能处理模块化语法,像是箭头函数、三点运算符等不支持,不支持的结果是原封不动输出,对IE兼容性会产生问题,然而2022年6月微软宣布彻底结束IE浏览器,由于缺少安全补丁支持,早晚会漏洞百出,逼迫政府与企业升级浏览器,对我们开发者来说是个好事,不需要在考虑兼容IE了,可以放心使用ES6语法

ESLint

  1. eslint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码
  2. 安装eslinteslint-webpack-plugin,已安装请忽略
    1
    npm install eslint eslint-webpack-plugin --save-dev
  3. plugin和loader使用有点不一样,loader可以直接用,plugin需要先引入后使用;所有插件都是构造函数,最终都是new调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const ESLintPlugin = require('eslint-webpack-plugin');

    module.exports = {
    plugins: [
    new ESLintPlugin({
    // 检测哪些文件
    context: path.resolve(__dirname, "src")
    })
    ],
    };
  4. 输入npx webpack指令,上面会报错,我们还需要配置eslintrc.js文件,在根目录下创建此文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    module.exports = {
    // 继承Eslint规则
    extends: ["eslint: recommended"],
    env: {
    node: true, // 启动node中全局变量
    browser: true // 启动浏览器中全局变量
    },
    parserOptions: {
    ecmaVersion: 6, // 使用es6语法
    sourceType: "module" // 用es module
    },
    rules: {
    "no-var": 2 // 不能使用var定义变量
    }
    };
  5. 上面完成后,webpack里的eslint插件可以使用了,但是编辑器安装的eslint插件会检测打包后的js文件,这个文件用的是var定义变量,此时文件会报错,我们需要写一个.eslintignore忽略文件,有点像git的忽略文件,这里写的dist是webpack配置的输出文件夹,将会忽略下面的全部文件;写好之后依旧会报错,重启下编辑器看看
    1
    dist

Babel

  1. 不需要考虑IE兼容问题了,跳过

处理html文件

  1. 安装HtmlWebpackPlugin,已安装请忽略
    1
    npm install --save-dev html-webpack-plugin
  2. 引入与调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const path = require('path');

    module.exports = {
    entry: './src/main.js',
    output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'static/js/main.js',
    },
    plugins: [
    new HtmlWebpackPlugin({
    // 模版:以public/index.html文件为模版,创建新的html文件
    // 新的html文件特点:1.结构和原来一致 2.自动引入打包输出的资源
    template: path.resolve(__dirname, "public/index.html")
    })
    ],
    }

本地服务器&自动化

  1. 每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化
  2. 安装webpack-dev-server,它是自动化工具,监视我们的文件,一旦发生改变自动重新打包,已安装请忽略
    1
    npm i webpack-dev-server -D
  3. 配置本地服务器
    1
    2
    3
    4
    5
    6
    7
    8
    module.exports = {
    // 本地服务器:它不会输出打包资源,而是在内存中编译打包
    devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true // 是否自动打开浏览器
    }
    }
  4. 输入npx webpack serve指令,开启本地服务器,这时会弹出一个页面
  5. 点击正在运行的终端窗口,按下组合键ctrl + c终止服务器

生产模式

  1. 开发完代码后,我们需要将打包的代码部署上线,以及做一些优化提升性能;开发与生产模式都有各自的配置文件,起到不冲突的作用,下面说一下开发与生产的区别
  2. 开发模式不需要输出,因为我们的本地服务器是在内存中编译
    1
    2
    3
    4
    5
    6
    7
    8
    module.exports = {
    output: {
    // 开发模式没有输出
    path: undefined,
    // 文件名需要指定
    filename: "static/js/main.js"
    }
    }
  3. 我们把开发与生产配置文件放在config文件夹里,分别起不同名字,开发配置文件名webpack.dev.js,生产配置文件名webpack.prod.js--config表示指定配置文件在哪里,下面是开发模式的终端指令
    1
    npx webpack serve --config ./config/webpack.dev.js
  4. 生产模式需要指定输出,上面文章有提到不重复说明了,主要是修改模式
    1
    2
    3
    module.exports = {
    mode: "production"
    }
  5. 我们只管输出打包文件,不需要运行服务器,下面是生产模式的终端指令
    1
    npx webpack --config ./config/webpack.prod.js
  6. 我可不希望每次输入一大串指令运行,修改下package.json的启动命令,简化指令后就非常方便了
    • 开发模式:npm run dev
    • 生产模式:npm run build
      1
      2
      3
      4
      5
      6
      7
      {
      "scripts": {
      "start": "npm run dev",
      "dev": "webpack serve --config ./config/webpack.dev.js",
      "build": "webpack --config ./config/webpack.prod.js"
      }
      }

提取css成单独文件

  1. css文件目前被打包到js文件中,当js文件加载时,才会创建一个style标签来生成样式。对于网站来说,会出现闪屏现象,用户体验不好,我们应该打包成单独css文件,通过link标签加载性能才好
  2. 安装mini-css-extract-plugin,本插件需要webpack 5才能正常工作
    1
    npm install --save-dev mini-css-extract-plugin
  3. 回顾一下上面的笔记,有一节处理样式资源,讲的是处理css、sass、less文件,它们都是依赖style-loader转成style标签插进html,这不是我们想要的结果,我们需要替换成mini-css插件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");

    module.exports = {
    module: {
    rules: [
    {
    test: /\.css$/,
    use: [
    // 执行顺序,从右到左(从下到上)
    // "style-loader",
    MiniCssExtractPlugin.loader, // 提取css成单独文件
    "css-loader",
    ],
    },
    ],
    },
    plugins: [
    new MiniCssExtractPlugin({
    filename: "static/css/main.css", // 它是输出路径
    })
    ],
    };
  4. 如果还有闪屏现象,先停止本地服务器,重新打包一次,再启动本地服务器。还有闪屏现象,就要考虑是不是图片太大的问题,或者配置文件写的不对

css兼容性处理

  1. 所谓的兼容性处理,全是为了兼容IE浏览器,上文已提过微软彻底停止IE浏览器,不需要特意去学了
  2. 好吧,执意要学的话,提供两种思路
    • autoprefixer:它是编辑器的插件,通常跟预处理器一起使用,自动生成兼容性前缀
    • postcss-loader:它是webpack兼容css的功能,你需要分别在webpack与package配置文件中进行配置

封装样式loader函数

  1. webpack配置文件越写越长,里面有很多重复代码,显得不美观不够优雅,试着提取代码封装到函数内
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    function getStyleLoader(pre){
    return [
    MiniCssExtractPlugin.loader, //提取css成单独文件
    "css-loader", // 将css资源编译成commonjs模块到js中
    {
    loader: "postcss-loader",
    options: {
    postcssOptions: {
    plugins: [
    "postcss-preset-env", //解决大多数样式兼容性问题
    ]
    }
    }
    },
    pre, // 将预处理器编译成css
    ].filter(Boolean); // 过滤没有传值的pre
    }

    module.exports = {
    module: {
    rules: [
    {
    test: /\.css$/,
    use: getStyleLoader(),
    },
    {
    test: /\.less$/,
    use: getStyleLoader("less-loader"),
    },
    {
    test: /\.s[ac]ss$/,
    use: getStyleLoader("sass-loader"),
    },
    ],
    }
    }

css压缩

  1. 减少css代码体积,让代码只显示在一行
  2. 安装css-minimizer插件,已安装请忽略
    1
    npm install css-minimizer-webpack-plugin --save-dev
  3. 引入与调用
    1
    2
    3
    4
    5
    const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

    module.exports = {
    plugins: [new MiniCssExtractPlugin()],
    };

html和js压缩

  1. 生产模式默认开启:html压缩和js压缩
  2. 不需要额外进行配置

webpack基础已学完,高级部分未完待续…