Webpack 基础 - 学习笔记

webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具

当 webpack 处理应用程序时,

  • 它会在内部从一个或多个入口点构建一个 依赖图 (dependency graph)
  • 然后将你项目中所需的每一个模块组合成一个或多个 bundles
    • 它们均为静态资源,用于展示你的内容。

从 v4.0.0 开始,webpack 可以不用再引入一个配置文件来打包项目。

01. 工作模式 mode

mode 参数:其默认值为 production

  • development:开发模式。
    • 没有进行代码优化。
    • 仅能编译 JS 中的 ES Module 语法(模块化语法)
      • 不会编译箭头函数、剩余参数语法
    • 打包更加快速。
  • production:生产模式。
    • 不仅能编译 JS 中的 ES Module 语法。
    • 还会进行 tree-shaking 和压缩代码。
    • 打包比较慢。
  • none

配置 mode:

  1. 在配置对象中提供 mode 选项
    module.exports = {
          
          
    	mode: 'development',
    };
    
  2. 从 CLI 参数中传递
    npx webpack --mode=development
    

在这里插入图片描述

npx 指令会将 node_modules 目录下的 .bin 添加为环境变量,因此可以访问该环境变量下的一些应用程序,包括 webpack.cmd 指令。

npx webpack [entry] --mode=[mode]
npx webpack ./src/main.js --mode=development

02. 配置文件

  1. 在根路径下新建一个配置文件 webpack.config.js
  2. 新增基本配置信息
    const path = require('path')
    
    module.exports = {
          
          
      mode: 'development', // 模式
      entry: './src/index.js', // 入口文件
      output: {
          
          
        filename: 'bundle.js', // 入口文件输出的目标文件
        path: path.join(__dirname, 'dist')	// 入口文件依赖的所有文件输出的根目录
      }
    }
    

03. Loader:处理 CSS

webpack 默认支持处理 JavaScriptJSON 文件。
其他类型都处理不了,必须借助 Loader 来对不同类型的文件进行处理。
在这里插入图片描述
安装 css-loader 来处理 CSS:

npm install css-loader -D
const path = require('path')

module.exports = {
    
    
  mode: 'development',
  entry: './src/index.js',
  output: {
    
    
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  + module: {
    
    
  +   rules: [
  +     {
    
    
  +       test: /\.css$/,
  +       use: 'css-loader'
  +     }
  +   ]
  + }
}
  • module.rules 中的配置对象,可以使用 use / loader 来指定要使用的 loader
    • use:可以使用多个 loader
    • loader:只能使用一个 loader

04. 插件 plugin:处理 HTML

插件可以贯穿 Webpack 打包的生命周期,执行不同的任务。

插件 html-webpack-plugin 会为应用程序生成一个 HTML 文件,且在导出的 HTML 文件中引入入口 JavaScript 文件(通过 defer 的方式),并自动将生成的所有 bundle 注入到此文件中。

可以通过配置使用已有的 html 文件作为模板。

npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')

module.exports = {
    
    
  mode: 'development',
  entry: './src/index.js',
  output: {
    
    
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    
    
    rules: [
      {
    
    
        test: /\.css$/,
        use: 'css-loader'
      }
    ]
  },
  + plugins: [
  +   new HtmlWebpackPlugin({
    
    
  +     template: './src/index.html'
  +   })
  + ]
}

在这里插入图片描述

05. 自动清空打包目录

webpack5

webpack5 在 output 选项中设置 clean: true 即可在每次构建时自动清空上次构建的目录。

  • 在打包前将 path 指定的目录整个清空。
module.exports = {
    
    
  // ...
  output: {
    
    
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    + clean: true
  },
  // ...
}

webpack4

webpack4 需要使用插件 clean-webpack-plugin

npm i clean-webpack-plugin -D
const {
    
     CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
    
    
  // ...
  plugins: [
    new HtmlWebpackPlugin({
    
    
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ],
  // ...
}

06. 引入 CSS

只靠 css-loader 只能处理 css,而无法将样式加载到页面上,需要通过 style-loader 来完成这个功能。

  • css-loader:将 css 资源编译成 commonjs 的模块打包到 JavaScript 中
  • style-loader :将 JavaScript 中的 css 通过创建 style 标签的形式添加到 html 文件中。
  1. 安装 style-loader

    npm i style-loader -D
    
  2. 配置 loader

    • loader 的执行顺序是从后往前。css-loaderstyle-loader
    module.exports = {
          
          
      // ...
      module: {
          
          
        rules: [
          {
          
          
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          }
        ]
      },
      // ...
    }
    
  3. 引用样式文件

    • 在入口文件 ./src/index.js 引入样式文件 ./src/index.css
    import './index.css'
    

    style-loader 的核心逻辑:

    • 通过动态添加 style 标签的方式,将样式引入页面。
    const content = `${
            
            样式内容}`
    const style = document.createElement('style');
    style.innerHTML = content;
    document.head.appendChild(style);
    

07. CSS 兼容性

使用 postcss-loader,自动添加 CSS3 部分属性的浏览器前缀。

npm install postcss postcss-loader postcss-preset-env -D
// webpack.config.js
module.exports = {
    
    
  // ...
  module: {
    
     
    rules: [
      {
    
    
        test: /\.css$/, //匹配所有的 css 文件
        use: [
          'style-loader',
          'css-loader', 
          'postcss-loader'
        ]
      }
    ]
  }, 
  //...
}

前置插件中有 autoprefixer,能够为 css 选择器增加不同的浏览器前缀

  • 其内部会根据 browserslist 指定浏览器版本
  • 然后在 caniuse 查找该浏览器版本的兼容性支持情况。
// postcss.config.js
module.exports = {
    
    
	plugins: [require('postcss-preset-env')]
}
// or 在 webpack.config.js 中进行配置
module.exports = {
    
    
  // ...
  module: {
    
     
    rules: [
      // ...
      {
    
    
        test: /\.css$/i,
        exclude: /node_modules/,
        use: [
          'style-loader',
          'css-loader', 
          // +
          {
    
    
            loader: 'postcss-loader', 
            options: {
    
    
              postcssOptions: {
    
    
                plugins: ["postcss-preset-env"]
              }
            }
          }
          // +
        ]
      },
      // ...
    ]
  },
  // ...
}

创建浏览器兼容的配置文件 .browserslistrc 指定兼容性处理的程度:

  • 也可以通过在 package.json 中添加 browserslist 字段进行配置
# 换行相当于 and
last 2 version # 回退 2 个浏览器版本
> 0.5%  # 全球超过 0.5% 的人使用的浏览器
not dead 
IE 10   # 兼容 IE 10

在这里插入图片描述

08. 引入 Less / Sass

Less 和 Sass 需要使用对应的 Loader 来处理:

  • Less:less-loader
  • Sass:sass-loader + node-sassdart-sass

Sass

安装 loader:

npm install sass-loader -D
npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/

在 index.js 中引入 sass 文件

import './sass.scss'

修改配置:

module.exports = {
    
    
   // ...
  module: {
    
    
    rules: [
      {
    
    
        test: /\.s[ac]ss$/i, //匹配所有的 sass/scss 文件
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
          'sass-loader', 
        ]
      },
    ]
  },
  // ...
}

Less

安装 loader:

npm install less less-loader -D

在 index.js 中引入 less 文件

import './less.less'

修改配置:

module.exports = {
    
    
   // ...
  module: {
    
    
    rules: [
     	// ...
      {
    
    
        test: /\.less$/i, //匹配所有的 less 文件
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
          'less-loader', 
        ]
      },
    ]
  },
  // ...
}

09. 分离样式文件

前面都是依赖 style-loader 将样式通过 style 标签的形式添加到页面上。

网页因此会出现闪屏的现象,用户体验不好。

使用单独的 CSS 文件,并通过 link 标签引入,性能表现更好。

通过 mini-css-extract-plugin 可以以 CSS 文件的形式将样式引入到页面上。并且会默认将所有的 css 文件打包成一个。

$ npm i mini-css-extract-plugin -D

替换 style-loaderMiniCssExtractPlugin.loader,并添加插件:

module.exports = {
    
    
   // ...
  module: {
    
     
    rules: [
      // ...
      {
    
    
        test: /\.css$/i,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader, // 添加 loader
          'css-loader',
          'postcss-loader'
        ] 
      },
      // ...
    ]
  },
  plugins:[
    // ...
    new MiniCssExtractPlugin({
    
    
      filename: '[name].[hash:8]:css'
    }),
    // ...
  ],
  // ...
}

在这里插入图片描述

10. CSS 压缩

使用 CssMinimizerWebpackPlugin 压缩 CSS 文件。

npm i css-minimizer-webpack-p
plugins: [
	...,
	new CssMinimizerPlugin(),
	...
]

默认生产模式已经开启了 html 压缩和 js 压缩,因此不需要进行额外的配置。

11. 处理图片资源

后续配置开发环境的时候,会使用 devServer 本地开启一个服务器,可以通过设置 contentBase / static 直接读取源目录中的静态文件,

但在生产环境中,引用资源的相对地址经过 webpack 打包后,会发生资源找不到的错误:

<img src="/logo.png" alt="">
<div id="imgBox"></div>
#imgBox {
    
    
	background: url('../public/logo.png');
}

需要在打包的时候处理一下。

webpack4:file-loader 和 url-loader

webpack4 常用的处理图片文件的 Loader 包含:

  • file-loader:将图片原封不动地输出到构建输出的目录。
    1. 解决打包后图片引入问题,会将图片 copy 到指定目录,默认为 dist
    2. 用于缓存资源的更新。
      • 可以根据文件内容计算出一个哈希值作为文件名。
      • hash 值变化时,意味着文件内容变化了。此时文件名发生改变,之前缓存的资源就失效了,会自动更新资源。
  • url-loader:将小于指定大小的图片转换为 base64 编码,减少 HTTP 请求的数量。
    • url-loader 包含了 file-loader
    • 当图片小于 limit 值时,会将图片转换为 base64 编码。
    • 大于 limit 值时仍然使用 file-loader 进行拷贝。
  • img-loader:压缩图片。

file-loader 的配置选项:

  • 图片名字 name
    • 默认值为:[contenthash].[ext]
  • 图片所在的文件夹 outputPathpublicPath

webpack5 中使用 file-loader / url-loader

在 webpack5 中使用 file-loaderurl-loader 会和内置的模块处理冲突:

1.dist 文件夹中多出一个显示不了的图片,并且构建后的 css 中引用的图片 url 指向这个显示不了的图片,导致在 html 中通过 css 引入的图片无法显示。

  • 错误原因:

    • css-loader 会默认转换 url 为 commonjs 模块:url(image.png) => require('./image.png')
    • 之后 file-loader 和 webpack5 中的 asset 模块默认都会其进行处理,发生了冲突
  • 解决方式:

    • 在使用旧的 assets loader (如file-loader / url-loader / raw-loader )和 asset 模块时,需要停止 asset 模块对资源的默认处理以免造成 asset 的重复。
    • 可以通过将 assets 模块的类型设置为 type: 'javascript/auto' 实现。

在这里插入图片描述

2.上述配置后, css 引用的图片 url 变成了 [Object%20Module],构建后图片依然显示不了。

  • 错误原因:
    • file-loader 新版本默认使用了 esModule 语法,造成了引用图片文件时的方式和以前的版本不一样
    • css-loader 对 url 的处理是使用 commonjs 语法
  • 解决方式:
    • 使 file-loader 不使用默认的 esModule 语法。
module:{
    
    
	rules:[
		{
    
    
      test: /\.(jpe?g|png|gif)$/i, 
      use: {
    
    
        loader: 'file-loader',
        options: {
    
    
          //不使用 esModule 的语法导出, 解决 css 引入图片 url 变成 [object%20Module]
          + esModule: false, 
          name:'[name][hash:8].[ext]'
        },
      },
      // 停止 webpack5 的 asset 模块对静态资源的默认处理。
      + type: 'javascript/auto',
    },
  ]
}

webpack5: asset 模块

webpack5 已经将两个 loader 的功能内置到 webpack 里面了,只需要进行简单的配置即可。

module: {
    
    
	rules: [
		{
    
    
			test: /\.(png|jpe?g|gif|webp|svg)$/i,
			type: 'asset'
		}
	]
}

将小图片转换为 base64 :

  • 减少 http 请求次数,减轻服务器的压力。
  • 转换后资源大小会增大。
    • 如果将大图片转换为 base64 会导致页面加载速度变慢
{
    
    
  test: /\.(png|jpe?g|gif|webp|svg)$/i,
  type: 'asset',
  parser: {
    
    
    dataUrlCondition: {
    
    
      // 小于 10 kb 的图片转 base64
      maxSize: 10 * 1024,
    }
  }
},

12. 修改输出文件目录

所有 bundles 的输出根目录可以通过 output 选项配置:

  • path: 修改所有文件的输出路径
  • filename:入口文件打包输出时使用的文件名

指定资源的输出目录 / 文件名可以通过 loader 中的 generator 选项配置:

  • [name]:原先的文件名
  • [fullhash]:根据文件计算出的一个哈希值
    • 也可以使用 [chunkhash] / [contenthash]
  • [ext]:文件原先的扩展名
  • [query]:请求携带的查询参数 ?a=b
{
    
    
  test: /\.(png|jpe?g|gif|webp|svg)$/i,
  type: 'asset',
  parser: {
    
    
    dataUrlCondition: {
    
    
      // 小于 10 kb 的图片转 base64
      maxSize: 10 * 1024,
    }
  },
  generator: {
    
    
    filename: "images/[name][contenthash:10][ext][query]"
  }
},

13. 处理字体资源

type 使用 asset/resource ,相当于是之前的 file-loader,直接将文件原封不动的输出,不需要转换为 Base64。

module: {
    
    
  rules: [
    {
    
    
      test: /\.(ttf|woff2?)$/i,
      type: "asset/resource",
      generator:{
    
    
        filename: "asset/fonts/[name].[contenthash:10][ext][query]"
      }
    }
  ],
}

14. 处理其他资源

只需要使用 type: "asset/resource" 原封不动的输出即可。

module: {
    
    
  rules: [
    {
    
    
      test: /\.(mp3|mp4|avi)$/i,
      type: "asset/resource",
      generator:{
    
    
        filename: "asset/resource/[name].[contenthash:10][ext][query]"
      }
    }
  ],
}

15. 处理 JavaScript 资源

webpack 对 JavaScript 的处理是有限的,只能编译 ES Module 模块化语法。

  • 通常我们会通过 Babel 再做一些兼容性处理。
  • 并通过 Eslint 来检查代码的格式。

Eslint

Eslint 是可组装的 JavaScript 和 JSX 检查工具。通过配置文件来定义代码规则。

① 配置文件

  • .eslintrc.* 需要位于项目根目录
    • .eslintrc
    • .eslintrc.js
    • .eslintrc.json
  • package.json 中的 eslintConfig 字段也可以进行配置。

.eslintrc.js 配置文件为例:

module.exports = {
    
    
	// 解析选项
	parserOptions: {
    
    },
	// 具体检查规则
	rules: {
    
    },
	// 继承其他规则
	extends: [],
	// ...
}
  1. parserOptions 解析选项:

    parserOptions: {
          
          
    	// ES 语法版本
    	ecmaVersion: 6,
    	// ES 模块化
    	sourceType: "module",
    	// ES 其他特性
    	ecmaFeatures: {
          
          
    		// react 项目需要开启
    		jsx: true
    	}
    }
    
  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' // 少数情况下不会有警告
    	]
    }
    
  3. extends 继承:

    • 可以继承现有规则。
    • 较为有名的规则:
      • eslint:recommended Eslint 官方的规则
      • plugin:vue/essential Vue Cli 官方的规则
      • react-app React Cli 官方的规则
// .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 配置 eslint 插件

eslint 以插件 ESLintWebpackPlugin 的形式配置,需要传入 options 选项:

  • context:配置哪个根目录下的文件需要进行检查。
plugins: [
  new ESLintWebpackPlugin({
    
    
    context: path.resolve(__dirname, 'src'),
  }),
]

配置 .eslintrcignore 文件,使 VSCode 的 Eslint 插件对 dist 目录下打包后的文件不进行代码格式检查。

Babel

JavaScript 编译器。用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 代码,以便能够运行在当前和旧版本的浏览器或其他环境中。

① 配置文件

  • babel.config.*:位于项目根目录的一个文件
    • babel.config.js
    • babel.config.json
  • .babelrc.*:位于项目根目录的一个文件
    • .babelrc
    • .babelrc.js
    • .babelrc.json
  • package.json 中的 babel:不需要创建文件,在原有文件的基础上写。

② 具体配置

babel.config.js 配置文件为例:

module.exports= {
    
    
	// 预设
	presets: []
}
  • presets 预设:一组 Babel 插件,扩展 Babel 的功能。
    • @babel/preset-env:一个智能预设,允许您使用最新的 JavaScript
      • 将 ES6+ 的语法编译为 ES5 的语法。
    • @babel/preset-react:用来编译 React jsx 语法的预设。
    • @babel/preset-typescript:用来编译 TypeScript 语法的预设。
    • 预设可以加载一个或多个。

③ webpack 配置 babel-loader

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

配置 loader:

module: {
    
    
	rules: [
		// ...
    {
    
    
      test: /\.js$/,
      exclude: /node_modules/,
      loader: "babel-loader",
      // 在此处配置 or 通过新建一个文件 babel.config.js 进行配置。
      // options: {
    
    
      //   presets: ["@babel/preset-env"]
      // }
    }
    // ...
	]
}
  

在这里插入图片描述

16. 启动 devServer

安装 webpack-dev-server

npm i webpack-dev-server -D

config 对象中的配置:

module.exports = {
    
    
  // ...
  module: {
    
    ...},
  plugins: [...],
  devServer: {
    
    
      host: 'localhost',
      // contentBase: webpack-dev-server version < 4.0.0 时使用 contentBase 替代 static 进行配置。
      static: path.resolve(__dirname, 'public'), // 静态文件目录
      compress: true, // 启动 gzip
      port: 8080,     // 端口号
      open: true      // 自动打开浏览器
  },
  // ...
}

启动本地服务:

npx webpack serve --mode=development

通过 devServer 启动,不会输出构建后的资源,是在内存中编译打包的。

配置 contentBase / static

使用 webpack 打包时,对静态文件(如图片)的处理都是直接复制到 dist 目录下面。对于本地开发来说,这个过程没有必要,太费时。

在设置 contentBase / static 之后,就可以直接到对应的静态资源目录下去读取文件,而无需对文件做任何移动,节省了时间和性能开销。

17. 区分环境

本地开发与部署上线有不同的需求:

  • 本地环境
    • 需要更快的构建速度
    • 需要打印 debug 信息
    • 需要 live reload / HRM 的功能(热重载)
    • 需要 sourcemap 方便定位问题
  • 生产环境
    • 需要通过 代码压缩 + tree-shaking 获得更小的包体积
    • 需要进行代码分割
    • 需要压缩图片体积

针对不同的需求,需要进行环境的区分。可以通过两种方式进行区分:

① cross-env

  1. 本地安装 cross-env

    npm i cross-env -D
    
  2. 配置启动命令

    package.json 中配置 scripts

    {
          
          
      "scripts": {
          
          
        "dev": "cross-env NODE_ENV=dev webpack serve --mode development",
        "test": "cross-env NODE_ENV=test webpack --mode production",
        "build": "cross-env NODE_ENV=prod webpack --mode production"
      },
    }
    
  3. 在 webpack 配置文件中获取环境变量

    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const path = require('path')
    
    + console.log('process.env.NODE_ENV=', process.env.NODE_ENV) // 打印环境变量
    
    const devConfig = {
          
          
      + // mode: 'development',
      entry: './src/index.js',
      output: {
          
          
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
      },
      module: {
          
           /* ... */ },
      plugins: [ /* ... */ ]// ...
    }
    
    + module.exports = (env, argv) => {
          
          
    +   console.log('argv.mode=', argv.mode) // 打印 mode 值
    +   switch(argv.mode) {
          
          
    +  		case 'development': return devConfig
    +  		case 'production': ...
    +   }
    + }
    
  4. 测试

    • npm run build
      在这里插入图片描述
    • npm run test

    在这里插入图片描述

    • npm run dev
      在这里插入图片描述

可以根据不同的环境动态修改 webpack 的配置。

② 两个配置文件

另一种区分环境的方式是通过创建两个文件: webpack.dev.jswebpack.prod.js

其中 webpack.dev.js 用于配置开发环境,webpack.prod.js 用于配置生产环境。

# 以开发环境执行
# 开发环境需要开启 devServer,因此需要有 serve
npx webpack serve --config webpack.dev.js
# 以生产环境执行
# 生产环境无需 devServer
npx webpack --config webpack.prod.js

两个环境的配置文件见下文。

18. 开发模式的配置

// webpack.dev.js
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const path = require('path')

const styleLoader = [
  MiniCssExtractPlugin.loader, // 将 css 输出为一个单独的文件
  'css-loader', 
  'postcss-loader' // 解决 css 兼容性问题,添加浏览器前缀
]

module.exports = {
    
    
  // 运行代码是在根目录运行的,因此 entry 的相对路径不需要进行修改
  // 绝对路径需要回退一个目录
  entry: './src/index.js',
  output: {
    
    
    filename: 'bundle.js',
    // 开发模式没有输出,因此 path 可以为 undefined
    path: path.join(__dirname, '../dist'),
    // clean: true
  },
  module: {
    
    
    rules: [
      // 样式资源
      {
    
    
        test: /\.css$/i,
        exclude: /node_modules/,
        use: [...styleLoader]
      },
      {
    
    
        test: /\.s[ac]ss$/i,
        exclude: /node_modules/,
        use: [
          ...styleLoader,
          'sass-loader'
        ]
      },
      {
    
    
        test: /\.less$/i,
        exclude: /node_modules/,
        use: [
          ...styleLoader,
          'less-loader'
        ]
      },

      // 图片资源
      {
    
    
        test: /\.(png|jpe?g|gif|webp|svg)$/i,
        type: 'asset',
        parser: {
    
    
          dataUrlCondition: {
    
    
            // 小于 10 kb 的图片转 base64
            maxSize: 10 * 1024,
          }
        },
        generator: {
    
    
          filename: "images/[name].[contenthash:10][ext][query]"
        }
      },
      // 字体资源
      {
    
    
        test: /\.(ttf|woff2?)$/i,
        type: "asset/resource",
        generator: {
    
    
          filename: "asset/fonts/[name].[contenthash:10][ext][query]"
        }
      },
      // 其他资源
      {
    
    
        test: /\.(mp3|mp4|avi)$/i,
        type: 'asset/resource',
        generator: {
    
    
          filename: "asset/resource/[name].[contenthash:10][ext][query]"
        }
      },
      // js 资源: babel 配置
      {
    
    
        test: /.js$/i,
        exclude: /node_modules/,
        loader: "babel-loader",
        // 也可以通过 babel.config.js 进行配置
        // options: {
    
    
        //   presets: ["@babel/preset-env"]
        // }
      }
    ]
  },
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // context: 检测哪些文件
      context: path.resolve(__dirname, '../src')
    }),
    new HtmlWebpackPlugin({
    
    
      template: path.resolve(__dirname, '../public/index.html')
    }),
    // require('postcss-preset-env'),
    new MiniCssExtractPlugin({
    
    
      filename: '[name].[hash:8].css'
    }),
  ],
  devServer: {
    
    
    host: 'localhost',
    port: 8080,
    open: true, // 自动打开浏览器
    compress: true, // 启用 gzip 压缩
    // 静态文件目录,webpack < 4.0.0 使用 contentBase 代替
    static: path.resolve(__dirname, "../public")
  },
  mode: 'development'
}

重命名为 webpack.dev.js 表示开发模式的配置

  • 由于没有输出打包的文件,因此 output.path 可以是 undefined,并关闭 output.clean
  • 更改文件的目录之后,需要改写所有的绝对路径,而不需要改写 entry 的相对路径,因为代码是在根目录进行运行的。

以开发模式的配置运行:

npx webpack serve --config ./config/webpack.dev.js

19. 生产模式的配置

webpack.prod.js 表示生产模式的配置

  • 开启 output.clean
  • 不需要 devServer
// webpack.prod.js
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const path = require('path')

const styleLoader = [
  MiniCssExtractPlugin.loader, // 将 css 输出为一个单独的文件
  'css-loader', 
  'postcss-loader' // 解决 css 兼容性问题,添加浏览器前缀
]

module.exports = {
    
    
  entry: './src/index.js',
  output: {
    
    
    filename: 'bundle.js',
    path: path.join(__dirname, '../dist'),
    clean: true
  },
  module: {
    
    
    rules: [
      // 样式资源
      {
    
    
        test: /\.css$/i,
        exclude: /node_modules/,
        use: [
          ...styleLoader
        ]
      },
      {
    
    
        test: /\.s[ac]ss$/i,
        exclude: /node_modules/,
        use: [
          ...styleLoader,
          'sass-loader'
        ]
      },
      {
    
    
        test: /\.less$/i,
        exclude: /node_modules/,
        use: [
          ...styleLoader,
          'less-loader'
        ]
      },

      // 图片资源
      {
    
    
        test: /\.(png|jpe?g|gif|webp|svg)$/i,
        type: 'asset',
        parser: {
    
    
          dataUrlCondition: {
    
    
            // 小于 10 kb 的图片转 base64
            maxSize: 10 * 1024,
          }
        },
        generator: {
    
    
          filename: "images/[name].[contenthash:10][ext][query]"
        }
      },
      // 字体资源
      {
    
    
        test: /\.(ttf|woff2?)$/i,
        type: "asset/resource",
        generator: {
    
    
          filename: "asset/fonts/[name].[contenthash:10][ext][query]"
        }
      },
      // 其他资源
      {
    
    
        test: /\.(mp3|mp4|avi)$/i,
        type: 'asset/resource',
        generator: {
    
    
          filename: "asset/resource/[name].[contenthash:10][ext][query]"
        }
      },
      // js 资源: babel 配置
      {
    
    
        test: /.js$/i,
        exclude: /node_modules/,
        loader: "babel-loader",
        // 也可以通过 babel.config.js 进行配置
        // options: {
    
    
        //   presets: ["@babel/preset-env"]
        // }
      }
    ]
  },
  plugins: [
    new ESLintWebpackPlugin({
    
    
      // context: 检测哪些文件
      context: path.resolve(__dirname, '../src')
    }),
    new HtmlWebpackPlugin({
    
    
      template: path.resolve(__dirname, '../public/index.html')
    }),
    // require('postcss-preset-env'),
    new MiniCssExtractPlugin({
    
    
      filename: '[name].[hash:8].css'
    }),
    new CssMinimizerPlugin(),
  ],
  // 生产模式不需要 devServer
  mode: 'production'
}

以生产模式的配置运行:

npx webpack serve --config ./config/webpack.prod.js

20. 设置运行指令

设置 package.jsonscript

因为使用运行指令的方式时,.bin 默认也会添加到环境变量中,因此无需添加开头的 npx

"scripts": {
    
    
  "start": "npm run dev",
  "dev": "webpack serve --config ./config/webpack.dev.js",
  "build": "webpack --config ./config/webpack.prod.js"
},

猜你喜欢

转载自blog.csdn.net/weixin_50290666/article/details/128607150