webpack配置

针对项目,添加各种配置扩展webpack打包能力

Posted by page on February 15, 2021

webpack配置

基本配置

mode

 配置模式, webpack 将使用相应模式的内置优化

自动注入mode对应值为 process.env.NODE_ENV 变量至js模块

module.exports = {
  mode: 'development',
};
// 等同于命令 webpack --mode=development

entry

入口文件;

传入字符串或数组,默认单入口 chunk 会被命名为 main.js

entry: './src/main.js',
// 或
entry: ['react', 'react-dom', 'redux', 'react-redux'] // 生成引入数组各项的入口chunk

传入对象,则属性的键(key)作为 chunk 的名称,值用于描述入口特性

entry: {
  home: './home.js',
  about: './about.js',
  contact: './contact.js',
}
// 或描述值
entry: {
  home: { import: './catalog.js', filename: 'pages/home.js' },
  about: { import: './about.js', filename: 'pages/[name][ext]' },
  shared: ['react', 'react-dom', 'redux', 'react-redux']
}

filename:默认入口 chunk 的输出文件名是从 output.filename 中提取出来的,但你可以为入口chunk指定自定义的输出文件名

output

clean

输出打包文件前清空 output 目录

chunkFilename

运行时按需加载的chunk的名称

默认 [id].js(模块id标识或output.filename[name]

filename

控制输出 bundle 的名称,单个入口文件仅作为静态名称解析 filename: 'bundle.js'

多个入口、代码拆分或引入插件都会创建多个 bundle,需解析为动态名称

// [id] [name] [chunkhash] [contenthash]
filename: '[name].bundle.js',

path

打包bundle输出根路径

 path: path.resolve(__dirname, 'dist'),

publicPath

输出目录对应的公开 URL

// VUE_APP_RES_URL: http://res.domain.com.cn/
publicPath: process.env.VUE_APP_RES_URL,

devServer

http://localhost:port/webpack-dev-server 路径下可访问本地服务静态文件目录

open

启动webServer后自动打开浏览器 open: true

port

配置服务的监听端口号 port: 8080

proxy

访问配置路径时,指定代理服务

proxy: {
  '/admin': 'http://api.domain.co,.cn'
}

proxy.changeOrigin

代理时不保留主机头来源

proxy: {
 '/admin': {
   target: 'http://api.domain.co,.cn',
   changeOrigin: true
 }
}

static

配置提供静态文件服务的目录

static: path.resolve(__dirname, './dist')

https

使用https协议 https: true

headers

配置所有响应的头部默认携带字段值

headers: {
  'X-Custom-Foo': 'bar',
  ...
}

client.logging

logging: [“info” | "warn" | "error"] 重载或热模块替换的日志级别

client.overlay

编译错误或警告时,在浏览器中是否显示全屏覆盖层;默认显示

// 仅错误时显示overlay
overlay: {
  errors: true,
  warnings: false,
}

client.progress

是否开启编译进度

devMiddleware

配置 webpack-dev-middleware 插件的server资源的中间处理

historyApiFallback

配置服务响应404时替代内容,为 true 则返回 index.html(可用于vue-router的history模式刷新丢失问题);

// 匹配路径替换不同响应资源
historyApiFallback: {
  rewrites: [
   { from: /^\/$/, to: '/views/landing.html' },
   { from: /^\/subpage/, to: '/views/subpage.html' },
   { from: /./, to: '/views/404.html' },
  ]
}

onBeforeSetupMiddleware

所有其他中间件之前执行,该配置具有自定义中间件作用;相关选项 onAfterSetupMiddleware

onAfterSetupMiddleware: function (devServer) {
  if (!devServer) {
    throw new Error('webpack-dev-server is not defined');
  }
  // 可用于mock接口,express中间件写法
  devServer.app.get('/some/path', function (req, res) {
    res.json({ custom: 'response' });
  });
}

devtool

控制是否、如何生成 source map

开发环境推荐

eval 生成source map,但不映射到原始代码,不能正确的显示行数

eval-cheap-module-source-map 源自 loader 的 source map 会得到更好的处理结果

生产环境推荐

none 不生成 source map

source-map  source map 作为一个单独的文件生成

hidden-source-map 与 source-map 相同,但不会为 bundle 添加引用注释

resolve

设置模块如何被 webpack 解析

alias

为目录下模块创建别名作为模块名

resolve: {
  alias: {
    "@": resolve("src"),
    "@components": resolve("src/components"),
    "@views": resolve("src/views"),
 }
}

extensions

后缀名解析按 extensions 顺序,默认值为 [".js", ".json", ".wasm"]

优化配置

Loader配置

sass-loader

npm install -D sass sass-loader
{
  test: /\.s[ac]ss$/,
  use: [
    "style-loader",
    "css-loader",
    {
      loader: "sass-loader",
      options: {
        additionalData: (content) => {
          const additionalData = `
            @import "~@/style/variables.scss";
            $env: "${process.env.NODE_ENV}";
            $staticUrl: "${process.env.VUE_APP_STATIC_URL}";
          `;
          return additionalData + content;
        }
      }
    }
  ]
}

babel-loader

npm i @babel/core @babel/preset-env babel-loader -D
{
  test: /\.js$/,
  exclude: /node_modules/,
  use: {
    loader: "babel-loader",
    options: { cacheDirectory: true }, // 开启缓存
  }
}

注: 发现浏览器环境不兼容时,通过 include 配置添加对依赖包转换

// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": "3.26.1"  // corejs依赖版本
      }
    ]
  ]
}
// .browserslistrc
> 1%
last 2 versions
not dead

vue-loader

文档:https://vue-loader.vuejs.org/zh/

npm install -D vue-loader vue-template-compiler

插件配置

HtmlWebpackPlugin

安装:npm i html-webpack-plugin -D

基本使用

const HtmlWebpackPlugin = require('html-webpack-plugin');

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

filename: 生成HTML文件名称

chunks: 指定引入的 chunk,默认所有chunk都会被引用

title: 生成HTML内容的 title标签内容

favicon: 配置favicon路径

meta: 注入meta标签

meta: {
  viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'
}

template: 允许依赖指定HTML模板文件而非生成

配置项注入方式,使模板动态应用于多页面

plugins: [
  new HtmlWebpackPlugin({
    title: '首页title'
  })
]
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
  </body>
</html>

html-loader

存在html-loader时,html-webpack-plugin依赖的HTMl模板也会被加载解析,允许借助loader增强HTML模板配置

{
  module: {
    rules: [
      {
        test: /\.html$/,
        loader: 'html-loader',
        ... // html-loader支持的其它增强配置

      }],
  },
  plugins: [
    new HtmlWebpackPlugin({
      ... // htmlWebpackPlugin.options/tags访问插件配置

      template: 'src/index.html'
    })
  ]
}
<html>
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
    <%= htmlWebpackPlugin.tags.headTags %>
  </head>
  <body>
    <%= htmlWebpackPlugin.options.bodyTags %>
  </body>
</html>

templateParams: 配置额外的参数变量供HTML模板使用

templateParameters: {
  'title': '使用params.title作为标题'
},
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title><%= title %></title>
  </head>
  <body>
  </body>
</html>

templateContent: 配置模板内容,字符串或返回字符串的函数

new HtmlWebpackPlugin({
  inject: false, // 禁用默认的配置注入 可选:head|body对应js脚本位置

  templateContent: ({htmlWebpackPlugin}) => `
    <html>
      <head>
        ${htmlWebpackPlugin.tags.headTags}
      </head>
      <body>
        <h1>Hello World</h1>
        ${htmlWebpackPlugin.tags.bodyTags}
      </body>
    </html>
  `
})

EslintWebpackPlugin

安装: npm i eslint-webpack-plugin -D

基本使用:

const ESLintPlugin = require('eslint-webpack-plugin');

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

options传入eslint运行参数,eslint配置通过 .eslintrc.js 声明;

options

exclude:排除文件与目录名,默认"node_modules"

emitWarning:是否发出eslint warning警告,默认开启

emitError:是否发出eslint error错误,默认开启

fix:是否启用eslint修复,默认未启用