Webpack 配置

2022-04-10  本文已影响0人  _于曼丽_

devtool

module.exports = {
  // 开发模式推荐
  devtool: 'eval-source-map'
  // 生产模式推荐
  devtool: 'source-map'
}

devServer

module.exports = {
  // hot 默认为 true
  hot: true,
  // 如果返回结果为 404,则重定向到 index.html
  historyApiFallback: true,
  client: {
    overlay: true,
  },
  devMiddleware: {
    publicPath: '/publicPathForDevServe'
  },
  // 设置静态资源目录的位置以及访问路径,如果不需要静态资源,则不需要设置 static 属性
  static: {
    directory: path.resolve(__dirname, 'assets'),
    publicPath: '/static'
  }
}

通过 http://[devServer.host]:[devServer.port]/webpack-dev-server 查看 devServer 提供的所有资源列表。
通过 http://[devServer.host]:[devServer.port]/[output.publicPath]/资源名称 来访问对应的资源。
如果提供了 devMiddleware.publicPath,则通过 http://[devServer.host]:[devServer.port]/[devMiddleware.publicPath]/资源名称 来访问对应的资源,但是通过插件生成的 html 和 css 文件当中所有资源引用的路径仍然使用的是 http://[devServer.host]:[devServer.port]/[output.publicPath]/资源名称。因此需要保证 output.publicPathdevMiddleware.publicPath 一致。

static 设置的是静态资源目录的位置,不是打包生成的文件的存放位置,devServer 打包生成的文件存放在内存中,不存放到硬盘目录。

static.publicPath 设置的是访问静态资源的路径,不是访问打包生成的资源的路径,打包生成的资源路径通过 output.publicPath 访问,静态资源路径访问的是直接存放在静态目录中的静态资源。

output

配置文件

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  mode: 'none',
  entry: {
    app: './src/app.js'
  },
  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'http://www.lishiqing.com/',
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.(jpg|jpeg|png|gif)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext][query]'
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].min.css'
    }),
    new HtmlWebpackPlugin()
  ]
}

output.filename

initial chunk 的文件名

占位符:

output.chunkFilename

non-initial chunk 的文件名,占位符参考 output.filename

output.clean

设置为 true,每次打包之前清理 output.path 目录中的所有内容,可以替代 CleanWebpackPlugin 插件。

output.path

定义资源存放的位置,例如根据以上的配置文件打包之后生成如下文件:

  1. 根据 output.filename:打包生成 app.bundle.js
  2. 根据 MiniCssExtractPlugin 插件的 options.filename:生成 css/app.min.css
  3. 根据图片资源的 generator.filename:生成 images/1.jpg

将 1 2 3 生成的资源都存放到 output.path 目录,dist/app.bundle.js dist/css/app.min.css dist/images/1.jpg

部署的时候,将该目录下的内容复制到服务器对应的目录即可。

output.publicPath

定义资源访问的路径

资源访问路径 = output.publicPath + 资源名称

output.publicPath 可以是绝对路径、相对于服务的路径、相对于页面的路径。不管是哪种路径,都要以 / 结尾

  1. 如果 output.publicPath 是绝对路径 http://www.lishiqing.com/

HtmlWebpackPlugin 生成的 index.html 文件:

<script defer src="http://www.lishiqing.com/app.bundle.js"></script>
<link href="http://www.lishiqing.com/css/app.min.css" rel="stylesheet">

MiniCssExtractPlugin 生成的 css 文件:

.container {
  background: url(http://www.lishiqing.com/images/01dfd42294af18c510ac.jpg) no-repeat;
}
  1. 如果 output.publicPath 是相对服务的路径 /backend/

HtmlWebpackPlugin 生成的 index.html 文件:

<script defer src="/backend/app.bundle.js"></script>
<link href="/backend/app.min.css" rel="stylesheet">

MiniCssExtractPlugin 生成的 css 文件:

.container {
  background: url(/backend/images/01dfd42294af18c510ac.jpg) no-repeat;
}
  1. 如果 output.publicPath 是相对页面的路径 ./backend/

HtmlWebpackPlugin 生成的 index.html 文件:

<script defer src="./backend/app.bundle.js"></script>
<link href="./backend/app.min.css" rel="stylesheet">

MiniCssExtractPlugin 生成的 css 文件:

.container {
  background: url(./backend/images/01dfd42294af18c510ac.jpg) no-repeat;
}

不管通过哪种路径设置 output.publicPath,都只是影响 HtmlWebpackPlugin 和 MiniCssExtractPlugin 生成的文件中引用其他资源的路径。具体能不能根据资源路径访问到相应的资源,还得正确的部署 output.path 目录到服务器。

在开发模式下,devServer 自动开启一个开发服务器,并且将所有打包生成的资源存储到内存当中,然后通过 http://[devServer.host]:[devServer.port]/[output.publicPath]/资源名称来访问对应的资源。 这时候 output.publicPath 应该设置为相对服务的路径,例如 /

如果你的页面希望在其他不同路径中找到资源文件,则可以通过 devServer 配置中的 devMiddleware.publicPath 选项进行修改。

在生产模式下,推荐将 output.publicPath 设置为绝对路径,然后将 output.path 目录部署与绝对路径对应的服务器中。

module.rules

配置文件

module: {
  rules: [
    {
      test: /\.css$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader']
    },
    {
      test: /\.js$/,
      include: [
          path.resolve(__dirname, 'src')
      ],
      exclude: [
          path.resolve(__dirname, 'src/node_modules'),
          path.resolve(__dirname, 'src/libs')
      ]
    }
  ]
}

module.rules 是匹配规则数组,数组中的每一项为一条匹配规则,以下称为 rule。每条 rule 包括匹配条件和匹配结果。

对于依赖图中的每个模块路径,都按照 module.rules 中的 rule 依次进行匹配。如果模块路径满足某个 rule 的匹配条件,则对该模块应用该 rule 的 匹配结果中指定的 loader 进行预处理。? 如果模块路径满足多个 rule 的匹配条件 ?

匹配条件包括 test include exclude 选项,每个选项为一个匹配条件,选项的值可以是:

如果某个 rule 同时有多个匹配条件选项,则模块路径必须同时满足所有的匹配条件,才会对模块应用匹配结果。test 和 include 具有相同的作用,都是必须匹配选项。exclude 是必不匹配选项(优先于 test 和 include)。

最佳实践:

以上配置文件的第二条 rule,如果某个模块不在 ./src/node_modules/ 和 ./src/libs/ 目录下,并且在 ./src/ 目录下,并且模块名以 .js 结尾,则满足该条 rule 的匹配条件。

配置实例

package.json

{
  "name": "demo15",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve --open --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^6.7.1",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.6.0",
    "style-loader": "^3.3.1",
    "webpack": "^5.72.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.8.1",
    "webpack-merge": "^5.8.0"
  }
}

webpack.common.js

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

module.exports = {
  entry: {
    app: './src/app.js'
  },
  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource'
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Production'
    })
  ],
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          chunks: 'all',
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor'
        }
      }
    }
  }
}

webpack.prod.js

const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = merge(common, {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin()
  ]
})

webpack.dev.js

const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-source-map',
  devServer: {
    hot: true,
    historyApiFallback: true,
    client: {
      overlay: true
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
})
上一篇 下一篇

猜你喜欢

热点阅读