webpack5 基础配置

Posted 奥特曼 

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack5 基础配置相关的知识,希望对你有一定的参考价值。

在开发中,我们会使用 vue、react、less、scss等语法进行开发项目,但是浏览器只能识别 js、css,或者说在js中使用了es6中的import 导入 这时候也需要打包工具去转换成浏览器可以识别的语句。  

一、使用webpack

1.初始化package.json

npm init -y

注意生成的package.json 中的name不要叫插件名称 否则下载不了。

2.下载依赖

npm i webpack webpack-cli -D

 3. 启用webpack

开发模式

npx webpack ./src/main.js --mode=development

生产模式

npx webpack ./src/main.js --mode=production

当然 你也需要新建一个 src/main.js的文件

npx webpack 是用来运行本地安装 Webpack 包的。

./src/main.js: 指定 Webpack 从 main.js 文件开始打包,不但会打包 main.js,还会将其依赖也一起打包进来。

--mode=xxx:指定模式(环境)

4. 查看输出文件 

默认输出到dist文件下。

二、基础配置

(1)5大核心概念

1. entry(入口):指示 Webpack 从哪个文件开始打包

2. output(输出):指示 Webpack 打包完的文件输出到哪里去,如何命名等

3. loader(加载器):webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析

4. plugins(插件):扩展 Webpack 的功能

5. mode(模式)主要由两种模式:开发模式:development、生产模式:production

根目录新建 webpack.config.js

module.exports = 
  // 入口
  entry: "",
  // 输出
  output: ,
  // 加载器
  module: 
    rules: [],
  ,
  // 插件
  plugins: [],
  // 模式
  mode: "",
;

 修改配置文件

// Node.js的核心模块,专门用来处理文件路径
const path = require("path");

module.exports = 
  // 入口
  // 相对路径和绝对路径都行
  entry: "./src/main.js",
  // 输出
  output: 
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "main.js",
  ,
  // 加载器
  module: 
    rules: [],
  ,
  // 插件
  plugins: [],
  // 模式
  mode: "development", // 开发模式    生产模式:production
;

有了入口和模式的配置 直接运行 即可 

npx webpack

(2) 处理样式资源

 1. 处理css资源

因为我们是将css引入到入口文件里面,一般情况下js是不能识别css 的所以我们要对css进行处理。

npm i css-loader style-loader -D
  • css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容

此时样式就会以 Style 标签的形式在页面上生效

webpack.config.js

  module: 
    rules: [
      
        // 用来匹配 .css 结尾的文件
        test: /\\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      ,
    ],
  ,

src/main.js

import './css/index.css'

 src/css/index.css

.box 
    width: 200px;
    height: 200px;
    background: skyblue;

 public/index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="../dist/main.js"></script>
<body>
    <div class="box"></div>
</body>
</html>

注意 html 引入的是打包后的文件 

npx webpack

2.处理less资源

npm i less-loader -D

 webpack.config.js

rules: [
      ...
      
        test: /\\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      ,
    ],

src/main.js

import './css/index.css'
import './less/index.less'

 当然像scss/sass、Stylus 也是相同的配置方法 具体可参考webpack官网

 

3. 处理图片资源

新增两张图片

src/images/2kb.png

src/images/avatar.png

使用进行打包,会默认在dist目录下 生成一个带有hash的图片名称,也并没有产生一个本地资源的目录,如果需要则需另外配置。

因为有一张图片是2kb的,每次访问都需要去进行请求资源,我们可以把小于 xx 之内的图片进行转换base64处理。

 // 加载器
  module: 
    rules: [
      
        test: /\\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: 
          dataUrlCondition: 
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          ,
        ,
      ,
    ],

这时候dist文件下 只会产生一个图片资源,另一个已被处理成base64资源。

4.修改输出资源的名称和路径

当然我们希望打包后的js在一个文件中,本地资源又在另一个文件中。

  output: 
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  ,


 // 加载器
  module: 
    rules: [
       
        test: /\\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: 
          dataUrlCondition: 
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          ,
        ,
        generator: 
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        ,
      ,,
      ,
    ],

 

打包结果: 

 

5. 清空上次打包资源

若不做当前处理,如果有相同会默认替换,如有更新会自动新增不删除原来打包文件。

 output: 
    path: path.resolve(__dirname, "dist"),
    filename: "static/js/main.js",
+   clean: true, // 自动将上次打包目录资源清空
  ,

6. 处理字体图标

资源文件 可去iconfont-阿里巴巴矢量图标库进行下载

  • src/fonts/iconfont.ttf

  • src/fonts/iconfont.woff

  • src/fonts/iconfont.woff2

  • src/css/iconfont.css

import './css/index.css'
import './less/index.less'
+ import './css/iconfont.css'
  module: 
    rules: [
          
            test: /\\.(ttf|woff2?)$/,
            type: "asset/resource",
            generator: 
              filename: "static/media/[hash:8][ext][query]",
            ,
          ,
    ]

 type: "asset/resource"type: "asset"的区别:

  1. type: "asset/resource" 相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理
  2. type: "asset" 相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式
  3. 如果还有其他文件类型需要处理 可以在test正则中继续添加  |mp3|mp4|avi

7. eslint配置

eslint 就是检测我们各种语法规范的,让不规范的代码进行提示

根目录新建 .eslintrc.js

module.exports = 
  // 解析选项
  parserOptions: ,
  // 具体检查规则
  rules: ,
  // 继承其他规则
  extends: [],
  // ...
  // 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
;

 1. parserOptions 解析选项

parserOptions: 
  ecmaVersion: 6, // ES 语法版本
  sourceType: "module", // ES 模块化
  ecmaFeatures:  // ES 其他特性
    jsx: true // 如果是 React 项目,就需要开启 jsx 语法
  

2. rules 具体规则

  • "off" 或 0 - 关闭规则
  • "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
  • "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
rules: 
  semi: "error", // 禁止使用分号
  'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
  'default-case': [
    'warn', // 要求 switch 语句中有 default 分支,否则警告
     commentPattern: '^no default$'  // 允许在最后注释 no default, 就不会有警告了
  ],
  eqeqeq: [
    'warn', // 强制使用 === 和 !==,否则警告
    'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
  ],

3. extends 继承

开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。

现有以下较为有名的规则:

// 例如在React项目中,我们可以这样写配置
module.exports = 
  extends: ["react-app"],
  rules: 
    // 我们的规则会覆盖掉react-app的规则
    // 所以想要修改规则直接改就是了
    eqeqeq: ["warn", "smart"],
  ,
;

在webpack中使用 

npm i eslint-webpack-plugin eslint -D
  • .eslintrc.js
module.exports = 
    // 继承 Eslint 规则
    extends: ["eslint:recommended"],
    env: 
      node: true, // 启用node中全局变量
      browser: true, // 启用浏览器中全局变量
    ,
    parserOptions: 
      ecmaVersion: 6,
      sourceType: "module",
    ,
    rules: 
      "no-var": 2, // 不能使用 var 定义变量
    ,
  ;
  

 webpack.config.js

const ESLintWebpackPlugin = require("eslint-webpack-plugin");

module.exports = 
   plugins: [
        new ESLintWebpackPlugin(
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "src"),
          ),
  ],

这时候如果你在编辑器中安装了eslint插件  在src目录下写一个带有var声明变量的代码就会提示,如果没下载则打包编译时会有报错提示。

8. 忽略eslint文件检查

在上面我们值配置了src目录下,但是装在编译器的eslint插件并不知道,所以他也是全局进行检查,例如我们打包生成后的文件就会标红,所以过滤掉dist目录。

 根目录新建.eslintignore

# 忽略dist目录下所有文件
dist

9.Babel 

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

定义 Babel 配置文件

  module: 
      
        test: /\\.js$/,
        // 排斥哪些文件
        exclude: /node_modules/,
          loader: 'babel-loader',
          options: 
            presets: ['@babel/preset-env']
          
      
    ],
  ,

当然如果配置项够多也可以提取options

babel.config.js

module.exports = 
    // 智能预设
    presets: ['@babel/preset-env']

 10.处理 Html 资源

html为什么需要打包呢,本身不就html吗 ?

这个html 是打包后的html 并且呢 他会引入打包后的js资源,内容也是和源文件一样的。

npm i html-webpack-plugin -D

webpack.config.js

 plugins: [
    new HtmlWebpackPlugin(
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "public/index.html"),
    ),
  ],

若new HtmlWebpackPlugin 中不写指定文件则只会引入js文件 不会生成相同的dom元素

11. 服务器自动化webpack-dev-server

每次都需要手动去刷新文件才去自动更新 webpack-dev-server就可以在本地服务器开启一个端口号,进行自动化更新

npm i webpack-dev-server -D
 module.exports =  
// 开发服务器
  devServer: 
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  
npx webpack serve

当然也可以配置package.json使用npm run 运行

  "scripts": 
    "dev": "webpack server",
    "build": "webpack",
  ,

就可以使用 

npm run dev 
npm run build 

12.Css 优化处理

提取 Css 成单独文件

Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式

这样对于网站来说,会出现闪屏现象,用户体验不好

我们应该是单独的 Css 文件,通过 link 标签加载性能才好

npm i mini-css-extract-plugin -D

webpack.config.js

将之前在module rules配置的 所有样式的"style-loader" 改成MiniCssExtractPlugin.loader

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = 
 module: 
    rules: [
      
        // 用来匹配 .css 结尾的文件
        test: /\\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      ,
      
        test: /\\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      ,
   ]
  

13.css兼容性处理

例如在一些网站中使用-webkit- 等其他前缀对浏览器进行兼容。下面插件就是对css样式自动配置

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

放到"css-loader"下面

  
            loader: "postcss-loader",
            options: 
              postcssOptions: 
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              ,
            ,
          ,
 // 插件
  plugins: [
      // 提取css成单独文件
      new MiniCssExtractPlugin(
        // 定义输出文件名和目录
        filename: "static/css/main.css",
      ),
  ],

 当然 如果过多可以封装成函数进行return 返回出去,基本上在开发中也不会引入多个css样式处理语言。

我们可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。


  // 其他省略
  "browserslist": ["ie >= 8"]

实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置: 


  // 其他省略
  "browserslist": ["last 2 version", "> 1%", "not dead"]

14. 压缩css

 npm install css-minimizer-webpack-plugin --save-dev

webpack.config.js

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = 
  // 插件
  plugins: [
     // css压缩
    new CssMinimizerPlugin(),
  ],

css 会从多行变成一行,对于js和html 不需要进行压缩,对于生产环境下会自动压缩成一行。

15.HotModuleReplacement

在修改某个文件进行打包时并不希望他是全部更新的,我修改了哪些就应该更新哪些文件

module.exports = 
  //...
  devServer: 
    hot: true,
  ,
;

此时 css 样式经过 style-loader 处理,已经具备 HMR 功能了。 但是 js 还不行。

JS 配置需要在main.js 入口文件中

// 判断是否支持HMR功能
if (module.hot) 
  module.hot.accept("./js/one.js");

// 第二个参数额外执行的事件
  module.hot.accept("./js/sum.js", function (sum) 
    const result2 = sum(1, 2, 3, 4);
    console.log(result2);
  );

在开发中各种框架的loader已经配置好了。

16.OneOf

打包时每个文件都会经过所有 loader 处理,虽然因为 test 正则原因实际没有处理上,但是都要过一遍。比较慢。如果匹配上一个就不需要再次匹配了。

在rules新增 oneOf:[ ] 

module: 
    rules: [
          //新增对象
          oneOf:[,...一堆loader]
      
    ]

17.Cache

每次打包时 js 文件都要经过 Eslint 检查 和 Babel 编译,速度比较慢。我们可以缓存之前的 Eslint 检查 和 Babel 编译结果,这样第二次打包时速度就会更快了。

  module: 
    rules: [  
        test: /\\.js$/,
        // 排斥哪些文件
        exclude: /node_modules/,
          loader: 'babel-loader',
          options: 
            presets: ['@babel/preset-env'],
+           cacheDirectory: true, // 开启babel编译缓存
+           cacheCompression: false, // 缓存文件不要压缩
          
      
    ]


 plugins: [
    new ESLintWebpackPlugin(
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
      exclude: "node_modules", // 默认值
+      cache: true, // 开启缓存
+      // 缓存目录
      cacheLocation: path.resolve( __dirname,"./node_modules/.cache/.eslintcache" ),
    )
]

18.图片压缩

npm i image-minimizer-webpack-plugin imagemin -D

无损压缩

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D

有损压缩

npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D

webpack.config.js 

const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");


module.export = 
optimization: 
    minimizer: [
       // 压缩图片
       new ImageMinimizerPlugin(
        minimizer: 
          implementation: ImageMinimizerPlugin.imageminGenerate,
          options: 
            plugins: [
              ["gifsicle",  interlaced: true ],
              ["jpegtran",  progressive: true ],
              ["optipng",  optimizationLevel: 5 ],
              [
                "svgo",
                
                  plugins: [
                    "preset-default",
                    "prefixIds",
                    
                      name: "sortAttrs",
                      params: 
                        xmlnsOrder: "alphabetical",
                      ,
                    ,
                  ],
                ,
              ],
            ],
          ,
        ,
      ),
    ]
  ,

只有在生产模式下打包是生效的。当批量图片压缩是比较方便,也可以手动找网站进行压缩。

当然webpack配置还有很多 可自行参考webpack官网。

以上是关于webpack5 基础配置的主要内容,如果未能解决你的问题,请参考以下文章

微前端之 Webpack5 的 module federation

从零实现Webpack5中的代码分割

webpack5 基础配置

学到了!Webpack5 新特性之增量编译

前端工程化9:Webpack构建流程分析,Webpack5源码解读

webpack5 查漏补缺