从0开始搭建一个可用的vue3-webpack5-template(二)

517 阅读3分钟

前言

在第一篇文章中,我们搭建了一个基于webpack5的vue3项目,现在我们就开始对这个乞丐版配置进行完善。 (这一期的完整代码可以在vue3-webpack5-templatetag0.0.2中看到)

v0.0.2 功能完善

区分环境

第一件事要做的就是区分环境,对此,我们需要按照cross-env这个依赖包

yarn add cross-env

然后对webpack.conf.js配置文件进行拆分,拆为webpack.base.conf.jswebpack.dev.conf.jswebpack.prod.conf.js三个文件,最后修改package.jsonscript的脚本

"scripts": {
    "dev": "cross-env NODE_ENV=dev  webpack serve --config ./build/webpack.dev.conf.js --color",
    "build": "cross-env NODE_ENV=prod webpack --config ./build/webpack.prod.conf.js --color"
  },

现在我们就可以通过执行不同的脚本命令,来使用不同环境的配置来构建应用,接下来我们再看看拆分后的配置是什么样的

配置拆分

首先是通用的webpack.base.conf.js,保留entry,resolvemodule以及部分通用的plugin

const { VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { resolve } = require('./utils.js')
module.exports = {
    entry: {
        app: resolve('src/main.js')
    },
    resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: { '@': resolve('src') }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        cacheDirectory: true
                    }
                },
                include: [resolve('src')]
            },
            // ...其他rule省略
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: resolve('public/index.html'),
            title: 'vue3-webpack-title'
        }),
        new VueLoaderPlugin()
    ]
}

然后是webpack.dev.conf.js,因为devServer中配置比较多,我们可以将这些配置单独放到build/config.js文件中进行统一管理,config文件内容如下

module.exports = {
    dev: {
        dev: {
        proxyTable: {},
        // Various Dev Server settings
        host: 'localhost', // can be overwritten by process.env.HOST
        port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
        autoOpenBrowser: true,
        errorOverlay: true,
        poll: false
    },
    },

    build: {}
}

接下来我们再看看webpack.dev.conf.js文件,首先需要合并webpack.base.conf.js,需要添加webpack-merge依赖包

yarn add webpack-merge -D

然后提取一些dev环境下特有配置即可,完整内容如下

const merge = require('webpack-merge')
const webpack = require('webpack')
const config = require('./config')

const baseWebpackConfig = require('./webpack.base.conf')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {
    module: {},
    devServer: {
        // http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename] 进行访问
        historyApiFallback: true,
        hot: true,
        client: {
            overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
            logging: 'none',
            progress: true
        },
        compress: true,
        host: HOST || config.dev.host,
        port: PORT || config.dev.port,
        open: config.dev.autoOpenBrowser,
        proxy: config.dev.proxyTable
    },
    plugins: [new webpack.HotModuleReplacementPlugin()]
})

module.exports = devWebpackConfig

接下来就是生产环境,webpack.prod.conf.js,同样的,只保留相关配置即可

const merge = require('webpack-merge'
const baseWebpackConfig = require('./webpack.base.conf')
const { resolve } = require('./utils')
const config = require('./config')

const webpackConfig = merge(baseWebpackConfig, {
   output: {
        path: resolve('dist'),
        filename: 'js/[name].[chunkhash].js',
        publicPath: './',
        clean: true
    }
})
module.exports = webpackConfig

性能优化

性能优化的话主要是针对于打包,也就是webpack.prod.conf.js,我们一个一个来。

css抽离

这个使用官方推荐的MiniCssExtractPlugin即可

yarn add mini-css-extract-plugin -D

修改webpack.base.conf.js文件,在rule中引入MiniCssPlugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const isProdMode = process.env.NODE_ENV === 'prod'
module.exports = {
    
    rules: [{
                test: /\.(css|scss|sass)$/,
                use: [
                    !isProdMode
                        ? 'style-loader'
                        : {
                              loader: MiniCssExtractPlugin.loader,
                              options: {
                                  publicPath: '../'
                              }
                          },
                    'css-loader',
                    'postcss-loader',
                    {
                        loader: 'sass-loader',
                        options: { implementation: require('dart-sass') }
                    }
                ]
            },
            // ...]
            
}

接着在webpack.prod.conf.js(注意是prod文件,不是base文件)中,引入MiniCssEExtractPlugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
webpackConfig = merge(baseWebpackConfig, {
    //...
    plugins: [new MiniCssExtractPlugin({
            filename: './css/[name].[contenthash].css',
            chunkFilename: './css/[id].[contenthash].css'
        }),// ...]
})
js/css压缩

这两个功能也是webpack5中已经有的,关于优化统一放到optimization中处理,首先添加TerserPluginCssMinimizerPlugin

yarn add css-minimizer-webpack-plugin terser-webpack-plugin  -D

然后在webpack.prod.conf文件中添加optimization配置

const TerserPlugin = require('terser-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
webpackConfig = merge(baseWebpackConfig, {
    //...
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                parallel: true,
                extractComments: false,
                terserOptions: {
                    compress: {
                        drop_console: true,
                        drop_debugger: true
                    }
                }
            }),
            new CssMinimizerPlugin()
        ],
        splitChunks: {
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    },
})

公共文件提取

这个比较简单,在webpack.prod.conf文件中添加splitChunks即可

webpackConfig = merge(baseWebpackConfig, {
    //...
    optimization: {
        // ...
        splitChunks: {
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    },
})

加快构建速度

这个需要利用webpack5新提供的cache属性

webpackConfig = merge(baseWebpackConfig, {
    //...
    cache: {
        type: 'filesystem',
        buildDependencies: {
            config: [__filename]
        },
        version: process.env.NODE_ENV
    }
})

简单解释一下这里面的配置信息,type可以设置为memoryfile-sysytem,如果设置为memory,则不再需要其他的配置。buildDependencies指定构建过程的代码依赖性, 官方推荐设置为 [__filename],当你任何使用require()的module发生改变时Persistent Caching就会无效.version 则可以简单理解成一个外部变量,如果这个变量变了,那么缓存失效

总结

好了,在这篇文章中,我们对配置进行了不同的环境区分,并且对打包过程进行了优化,但是结束了吗?并没有,还有许多可以添加的配置和优化项等着我们完成,如果你已经消化完了这篇文章中的内容,那么开始下一篇吧