webpack基础 | 青训营笔记

143 阅读7分钟

这是我参与「第四届青训营 」笔记创作活动的的第7天

webpack 作为市面上一种流行的构建工具,其作用不言而喻,下面是我整理的一些关于 webpack 的基础知识,更加详细的情参考官方文档哦。

webpack简介

webpack是什么

WebPack是一种前端资源构建工具,一个静态模块打包器(module boundler)。

在WebPack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。

它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(boundle)。

Webpack的作用

  1. 多分资源打包成一个 Bundle
  2. 支持 Babel,Eslint,TS,CoffeScript,Less,Sass
  3. 支持模块化处理 css ,图片 等资源文件
  4. 支持 HMR + 开发服务器
  5. 支持持续监听,持续构建
  6. 支持代码分离
  7. 支持 Tree-shaking
  8. 支持 Sourcemap

WebPack五个核心概念

  • Entry

    入口(Entry)指示WebPack以哪个文件为入口起点开始打包,分析构建内部依赖图。

  • Output

    输出(Output)指示Webpack打包后的资源bundles输出到哪里去,以及如何命名。

  • Loader

    Loader让Webpack能够去处理那些非JavaScript文件(类似css,img)(Webpack自身职能理解JavaScript)

  • Plugins

    插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。

  • Mode

    Webpack有两种模式:

    development:能让代码本地调试运行的环境

    production:能让代码优化上线运行的环境

webpack的核心流程

webpack核心流程.png

Webpack安装

//在终端运行如下的命令,安装webpack相关的两个包
npm install webpack webpack-cli  -D

webpack配置

webpack的配置主要分为两个方面:

  1. 流程类:作用于流程中某个 or 若干个环节,直接影响打包的配置项
  2. 工具类:主流程之外,提供了更多工程化能力的配置

webpack配置.png

流程类(开发)

webpack流程类配置.png

配置启动命令

项目的基本文件结构:

project_name
|—— src
|    |—— index.js
|—— package.json 
|—— webpack.config.js

此时,你可以直接运行命令:

npx webpack

或者,你在 package.json 文件中的 script 节点下运行新增一个 dev 脚本。

"scripts":{
    "dev":"webpack" 
}
// 此时,你就可以在终端中运行 npm run dev 来运行 webpack 了

配置mode属性

// webpack.config.js
module.exports = {
  mode: 'development',
}
development
  • 开发环境
  • 不会对打包生成的文件进行代码压缩和性能优化
  • 打包速度快,适合在开发阶段使用
production
  • 生产环境
  • 会对打包生成的文件进行代码压缩和性能优化
  • 打包速度很慢,仅适合在项目发布阶段使用

配置入口和出口文件

  • 单入口

    打包形成一个chunk。输出一个bundle.js

    const path = require("path");
    ​
    module.exports = {
      mode: "development",
      entry: "./src/index.js",
      output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "./dist"),
      }
    };
    
  • 多入口

    数组的形式:打包形成一个chunk。输出一个bundle.js

    module.exports = {
      mode: "development",
      entry: ["./src/index.js","./src/add.js"],
      output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "./dist"),
      }
    };
    

    对象的形式:有几个入口文件就形成几个chunk,输出几个bundle文件

    module.exports = {
      mode: "development",
      entry: {
        index:'./src/js/index.js',
        add:'./src/js/add.js'
      },
      output: {
        path: path.resolve(__dirname, "build"),
        filename: "[name].js",
      },
    }
    

webpack5 在 出口文件中添加一个 clean 属性,可以实现 webpack4 中 clean-webpack-plugin 的功能,打包时自动清理掉 dist 目录下的旧文件

output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[name].js",
    // 自动清空上次打包的内容
    // 原理:在打包前,将 path 整个目录清空,再进行打包
    clean:true,
},

配置devSever

devSever:{
    // 不会输出资源,在内存中打包
    open:true,//初次打包完成,会自动打开浏览器
    host:'127.0.0.1',//实时打包所使用的主机地址
    port:80,//实时打包所使用的端口号
}

凡是修改了webpack.config.js配置文件,或者修改了package.json配置文件,必须重启实时的打包服务器,否则最新的配置文件无法生成

webpack核心流程.png

webpack-dev-server的使用

上面说了,凡是修改了webpack.config.js配置文件,或者修改了package.json配置文件,必须重启实时的打包服务器,否则最新的配置文件无法生成,所以我们可以使用webpack-dev-server这个插件,来自动打包

webpack-dev-server 类似于node.js阶段用到的nodemon工具 每次修改了源代码,webpack会自动进行项目的打包和构建

安装

npm install webpack-dev-server -D

配置

"scripts":{
    "dev":"webpack-dev-server",
}
// 再次运行npm run dev 命令,重新进行项目的打包
// 在浏览器中访问http://lacalhost:8080地址,查看自动打包效果
//还可以这样去在webpack.config.json中取配置
devServer:{
    static:resolve(__dirname,'dist'),
    compress:true,
    port:3000,
    open:true//初次自动打开
}

配置plugin

打包处理HTML资源

安装

npm install html-webpack-plugin -D

作用

默认会创建一个空的HTML,自动引入打包输出的所有资源(js/css)

使用

const Htmlplugin = require('html-webpack-plugin')
​
const htmlPlugin = new Htmlplugin({
    template:'./src/index.html',//指定原文件的存放路径
    filename:'./index.html',//指定生成的文件的存放路径
})
​
module.exports = {
    mode:'development',
    plugins:[htmlPlugin],
}
const HtmlWebpackPlugin = require('html-webpack-plugin') 
const path = require('path')
module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, './src/index.html'), //原文件存放路径
      filename: path.join(__dirname, './dist/index.html'), //输出文件路径
    }),
  ],
}
​

作用:通过HTML插件复制到项目根目录中的index.html页面,也被放到了内存当中 HTML插件在生成的index.html页面,自动注入了打包的main.js文件

配置loader

webpack默认只能打包处理 .js 的文件,处理不了其他的后缀的文件。

image-20211225143748510

打包处理css样式资源

  • css-loader 是将css文件编程commonjs模块加载到js中,里面的内容是样式字符串
  • style-loader 是创建style标签,将js中的样式资源插入进行,添加到 head 中生效

安装

npm i style-loader css-loader -D

使用

module:{
    rules:[
        {
            test:/.css$/,
            use:['style-loader','css-loader']
        }
    ]
}

webpack把index.css这个文件,先转交给最后一个loader进行处理(先转交给css-loader)

当css-loader处理完毕之后,会将处理的结果,转交给下一个loader(转交给style-loader)

当style-loader处理完毕后,因为没有下一个loader了,于是就把处理结果,转交给了webpack

webpack吧style-loader处理结果,合并到了/dist/main.js中,最终生成打包好的文件

打包处理less资源

安装

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

使用

module:{
    rules:[
        {
            test:/.less$/,
            use:['style-loader','css-loader','less-loader']
        }
    ]
}

打包处理sass资源

安装

npm i style-loader css-loader sass-loader sass -D

使用

module:{
    rules:[
        {
            test:/.s[ac]ss$/,
            use:['style-loader','css-loader','sass-loader']
        }
    ]
}

打包图片资源

在过去的 webpack4 的时候 ,我们是用 url-loaderfile-loader 来处理图片

安装

npm i url-loader file-loader -D

使用

module:{
    rules :[
        {
        test: /.jpg|png|gif$/,
        use: {
            loader: "url-loader",
            options: {
               limit:4*1280,
              //明确指定把打包生成的图片文件,储存到dist目录下的image文件夹中
              outputPath:'image',
              esModule: false,
            },
          },
        type: "javascript/auto",
      },
    ]
}

当图片文件小于 limit 中的数值时,图片会转成 base64 的形式,这时我们发现,在 image 目录下没有该图片

但是当图片文件大于 limit 中的数值的时候,图片就会存放在 image 目录下

url-loader是ES5中的语法,ES6已经废弃,如果想要使用,需要加esModule: false,和type: "javascript/auto"

webpack5 中这两个 loader 的功能已经内置到 webpack 中了,我们只需要简单的配置就可以打包图片资源。

module:{
    rules :[
        {
            test: /.(png|jpe?g|gif|webp|svg)$/,
            type: "asset",
            parser: {
                dataUrlCondition: {
                    maxSize: 10 * 1024,
                },
            },
            generator: {
                filename: "static/image/[hash][ext][query]",
            },
        },
    ]
}

打包其他资源

module:{
    rules :[
        {
            // 之后有什么资源 往后面加就可以了
            test: /.(ttf|woff2?|map3|map4|avi)$/,
            type: "asset/resource",
            generator: {
                filename: "static/media/[hash][ext][query]",
            },
        },
    ]
}

js兼容性问题(babel)

安装

npm i -D babel-loader @babel/preset-env @babel/polyfill @babel/core core-js

使用

module: {
    rules: [
        {
            test: /.js$/,
            // 排除 模板 中的js问你件
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                // 可以直接在这里写配置,也可以单独的创建一个 babel.config,js 来写配置
                options: {
                    presets: ['@babel/preset-env']
                }
            }
        }
    ]
},

流程类(生产)

单独提取css文件

安装

npm i mini-css-extract-plugin -D

使用

const MiniCssExtractPlugin = require("mini-css-extract-plugin")
​
module: {
    rules: [
      {
        test: /.css$/,
        use: [
            //将所有使用 style-loader 的地方都替换成这个(打包less和sass的地方)
             MiniCssExtractPlugin.loader,
             "css-loader"
            ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
        filename:'static/css/built.css'
    })
  ],

解决css兼容性问题

安装

npm i postcss-loader postcss postcss-preset-env -D

使用

module: {
    rules: [
      // 打包处理 css
      {
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env", //能解决大多数的样式兼容问题
                  ],
                ],
              },
            },
          },
        ],
      },
      // 打包处理 less
      {
        test: /.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env", //能解决大多数的样式兼容问题
                  ],
                ],
              },
            },
          },
          "less-loader",
        ],
      },
    ],
  },

注意 postcss-loader 要在 css-loader 和 less-loader之间,不要把顺序搞错了

package.json中新增节点

"browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }

压缩css

安装

npm install css-minimizer-webpack-plugin -D

使用

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
​
module.exports = {
  module: {
    rules: [
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
  // 注意,一般不要使用这个,因为一旦使用了,那么 js的默认打包不知道为什么就消失了 
  // optimization: {
  //   minimizer: [
  //     new CssMinimizerPlugin(),
  //   ],
  // },
  plugins: [new MiniCssExtractPlugin()],
};

这将仅在生产环境开启 CSS 优化。

如果还想在开发环境下启用 CSS 优化,请将 optimization.minimize 设置为 true:

module.exports = {
  optimization: {
    // [...]
    minimize: true,
  },
};

压缩html和js

在 webpack5 中,webpack 在 production 模式默认将js 和 html 进行打包

原理如下

压缩js

安装

npm i terser-webpack-plugin -D

使用

const TerserPlugin = require('terser-webpack-plugin');
​
optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
},

压缩html


plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      filename: "index.html",
      minify:{
        //加上这两个属性就可以压缩了
        //压缩空格
        collapseWhitespace:true,
        //删除注释
        removeComments:true,
      }
    }),
 ],

结语

文章如果有不正确的地方,欢迎指正,共同学习,共同进步。

若有侵权,请联系作者删除。