webpack 常用配置+实战

78 阅读2分钟

前言

作为前端,在日常开发项目中,我们常使用vuereact来开发项目。webpack在其中起到了很重要的作用,下面我们就去认识一下。

本文开发版本
  • webpack 5.73.0
  • vue 3.2.37
  • npm 7.21.0

1. 搭建一个本地服务

在平常开发项目时,我们会先搭建一个开发环境,用于本地调试。本文先使用webpackwebpack-dev-server简单搭建一个vue本地服务,然后再一一学习相应的内容。

1.1 初始化

新建一个目录,初始化一个package.json文件

npm init -y

安装几个需要用到的包

npm install webpack webpack-cli webpack-dev-server --save-dev
npm install vue vue-loader --save-dev
npm install html-webpack-plugin --save-dev

1.2 新建文件

在根目录新建以下几个文件:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>hello webpack</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

src\main.js

import { createApp } from "vue"

import App from './App.vue'

const app = createApp(App)

app.mount('#app')

src\App.vue

<template>
    <div>hello webpack</div>
</template>

build\dev.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
    mode: 'development', // 开发模式
    entry: {
        app: path.resolve(__dirname, '../src/main.js')
    },
    devServer: {
        hot: true,
        host: 'localhost',
        open: false,
        port: 8866
    },
    module: {
        rules: [
            {
              test: /\.vue$/,
              use: [
                { loader: 'vue-loader' }
              ]
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
          filename: 'index.html',
          template: 'index.html',
          inject: true
        })
    ]
}

最后在package.json文件scripts中新增dev属性:

  "scripts": {
    "dev": "webpack-dev-server --config build/dev.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

完成以上操作后,运行npm run dev命令,然后在浏览器中输入地址http://localhost:8866/,浏览器会显示hello webpack,能成功显示说明配置成功了。

2. 对项目进行打包

通过上面的配置搭建好了一个开发服务,但开发完以后需要打包上线。下面来看下打包需要配置那些。

2.1 配置output

在build\prod.js 添加输出配置output: 表示打包后文件存放位置

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
    mode: 'production', // 生产模式
    entry: {
        app: path.resolve(__dirname, '../src/main.js')
    },
    module: {
        rules: [
            {
              test: /\.vue$/,
              use: [
                { loader: 'vue-loader' }
              ]
            }
        ]
    },
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: 'static/js/[name].[chunkhash:8].js',
        publicPath: '/'
    },
    plugins: [
        new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
          filename: 'index.html',
          template: 'index.html',
          inject: true
        })
    ]
}

2.2 使用babel转义

其中需要注意它们的版本,我这里使用了固定版本。

babel-loader@8.1.0

@babel/core@7.1.6

@babel/preset-env@7.1.6

安装
npm install babel-loader@8.1.0 @babel/core@7.1.6 @babel/preset-env@7.1.6 --save-dev
使用

build\prod.js

module.exports = {
    ...,
    module: {
        rules: [
            ...,
          {
            test: /\.js$/,
            use: ['babel-loader'],
            exclude: /(node_modules)/,
            include: [resolve('src'), resolve('test')]
          }
        ]
    },
}

然后在package.json文件scripts中新增build属性:

  "scripts": {
    "dev": "webpack-dev-server --config build/dev.js",
    "build": "webpack --config build/prod.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

构建配置时,完成上面两个的修改,运行npm run build命令,会生成一个dist目录,打包后的文件都保存在这个目录。

3 配置分析

完成上面两个步骤后,我们可以正常运行和打包项目。接下来就来分析一下每个属性的配置。

入口(entry): entry可有多种配置方式

    entry: path.resolve(__dirname, '../src/main.js'),
    entry: ['./app/entry1', './app/entry2'],
    entry: {a: "./app/entry-a", b: ["./app/entry-b1", "./app/entry-b2"]}

输出(output)

    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: '[name].js',
        publicPath: '/'
    }

模式(mode)

    mode: 'production', // 生成
    mode: 'development', // 开发
    mode: 'none',

模块配置(module.rules): 可有多种配置方式

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

插件(plugin):html-webpack-plugin、vue-loader

const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    })
]

4. 插件(plugins)配置

4.1 清理构建文件夹:clean-webpack-plugin

每次打包构建之前先清理文件夹内容的文件(文本构建后的文件保留在dist文件夹),保留最新构建的文件。

安装

npm install clean-webpack-plugin --save-dev

使用

build\prod.js

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

module.exports = {
    ...,
    plugins: [
        new CleanWebpackPlugin()
    ]
}

配置完成后,运行npm run build命令,会发现dist中上一次打包的文件会被清理掉。

4.2 提取css:mini-css-extract-plugin

1. 首先我们要保证样式能在开发模式下能正常运行,我们需要先安装vue-style-loadercss-loader,如果配置成功,当我们在.vuestyle标签中添加样式是会生效的。

 2. 完成这一步后,当打包的时候,就需要配置mini-css-extract-plugin.

安装

npm install css-loader --save-dev
npm install vue-style-loader --save-dev
npm install clean-webpack-plugin --save-dev

使用

build\dev.js

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

build\prod.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    ...,
    module: {
        rules: [
            ...,
            {
              test: /\.css$/,
              use: [
                'vue-style-loader',
                MiniCssExtractPlugin.loader,
                { loader: 'css-loader' }
              ]
            }
        ]
    },
    plugins: [
        ...,
        new MiniCssExtractPlugin({
          filename: 'static/css/[name]_[chunkhash:8].css',
          chunkFilename: 'static/css/[id]_[chunkhash:8].css'
        })
    ]
}

打包构建好以后,我们打开dist目录,查看是否生成.css后缀的文件,有说明已经成功了。

4.3 清理构建文件夹:copy-webpack-plugin

复制单个文件或者目录到构建目录。

安装

npm install copy-webpack-plugin --save-dev

使用

build\prod.js

const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    ...,
    plugins: [
        new CopyWebpackPlugin({
          patterns: [
            {
              from: path.resolve(__dirname, '../static'), // 需要拷贝的目录
              to: 'static2', // 拷贝到那个目录下
              globOptions: {
                ignore: ['.*'] // 拷贝的文件类型
              }
            }
          ]
        })
    ]
}

5. 优化(optimization)配置

5.1 splitChunks

这里会创建一个vendorchunk文件,它包含整个node_modules文件的代码。
使用

build\prod.js

module.exports = {
    ...,
    optimization: {
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendor',
            minSize: 0,
            minChunks: 1,
            chunks: 'all'
          }
        }
      }
    }
}

6. 其它

6.1 处理图片、媒体、字体等文件

通常是使用file-loader来实现,一般会和url-loader搭配使用。

安装

npm install file-loader url-loader --save-dev

使用

build\prod.jsbuild\dev.js

const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    ...,
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
        resourceQuery: /\?.*/,
        type: 'asset/inline',  
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset/resource',
        type: 'asset',
        generator: {
          filename: 'static/img/[name][ext]'
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        type: 'asset/resource',
        type: 'asset',
        generator: {
          filename: 'static/fonts/[name][ext]'
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/media/[name].[ext]'
        }
      }
    ]
  }
}

结语

我们在学习webpack的时候一定要边看边跟着敲(时间够的话敲个三四遍),这样才能知道每个属性、属性值的意义,影响也会更深。虽然这样花费的时间比较多,但是效果还是很显著的。

前端的内容更新迭代太快,我们只有不断学习才能跟上节奏。

共勉~~~

本文的代码地址:gitee.com/xia_ming/st…