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

前言

在上一篇文章中,我们对配置进行了抽离和优化,在这篇文章中,我们会进一步的完善和优化我们的template,这一篇文章的代码可以在vue3-webpack5-templatetag1.0.0中看到,现在开始吧

webpack配置完善

虽说已经添加了不少配置,但还是有很多功能没有用到,现在我们一个一个的来加上去

devtool

devtoool控制是否生成以及如何生成sourcemap,有很多值可以选择,开发环境下,为了加快构建速度,我们可以选择eval,生产环境下,为了更高质量的sourcemap,我们可以选择值为source-map,不过相应的会降低打包速度,大家可以自己根据速度与质量来进行权衡。
对于devtool和接下来的一些配置,我们可以将它们放在config.js中统一管理

module.exports = {
    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, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
        /**
         * Source Maps
         */
        // https://webpack.js.org/configuration/devtool/#development
        devtool: 'eval-cheap-module-source-map',
        cssSourceMap: true
    },

    build: {
        productionSourceMap: true,
        // https://webpack.js.org/configuration/devtool/#production
        devtool: 'source-map',

        // Gzip off by default as many popular static hosts such as
        // Surge or Netlify already gzip all static assets for you.
        // Before setting to `true`, make sure to:
        // yarn add --save-dev compression-webpack-plugin
        productionGzip: false,
        productionGzipExtensions: ['js', 'css'],

        // Run the build command with an extra argument to
        // View the bundle analyzer report after build finishes:
        // `yarn run build --report`
        // Set to `true` or `false` to always turn it on or off
        bundleAnalyzerReport: process.env.npm_config_report
    }
}


复制代码

mode

mode 是webpack内部的一个配置选项,告知 webpack 使用相应模式的内置优化
支持以下字符串值:

选项 描述
development 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名。
production 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPlugin 和 TerserPlugin 。
none 不使用任何默认优化选项

如果没有设置,webpack 会给 mode 的默认值设置为 production。我们在对应的环境中设置好对应的mode值即可

stats

用来控制打包后的bundle信息怎么显示,在dev环境中,我们一般使用 'errors-only,不然每次都会有一大堆的输出结果在命令行中,看起来很乱,而在prod环境中我们可以设置为normal

performance

性能提示相关,如果超出了设置的大小,则会打印对应的提示信息,这个我们可以只配置在webpack.prod.conf.js

完整配置

好了,现在我们来看一下添加这些配置项以后各个文件的内容吧,首先是webpack.dev.conf.js

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, {
    mode: 'development',
    module: {},
    stats: 'errors-only',
    devtool: config.dev.devtool,
    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, {
    mode: 'production',
    devtool: config.build.productionSourceMap ? config.build.devtool : false,
    output: {
        path: resolve('dist'),
        filename: 'js/[name].[chunkhash].js',
        publicPath: './',
        clean: true
    },
    stats: 'normal',
    cache: {//...},
    performance: {
        maxEntrypointSize: 5 * 1024 * 1024,
        maxAssetSize: 3 * 1024 * 1024,
        hints: 'warning'
    },
    optimization: {//...},
    plugins: [//...]
})


module.exports = webpackConfig

复制代码

功能添加

接下来,我们参考vue-cli提供的功能,进一步完善我们的配置,首先是针对开发环境

portfinder

如果配置的端口号已经被占用,则自动+1,这个功能需要用到portfinder,具体使用我们会结合下一个插件一起讲

yarn add portfinder -D
复制代码

FriendlyErrorsPlugin

自定义打包成功时的提示信息,感兴趣的同学可以在每次dev-server启动成功后打印出一个皮卡丘

yarn add friendly-errors-webpack-plugin -D
复制代码

这两个插件都是用在webpack.dev.conf.js中,具体代码如下:

const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
// ...
const devWebpackConfig = merge(baseWebpackConfig,{...})
module.exports = new Promise((resolve, reject) => {
    portfinder.basePort = process.env.PORT || config.dev.port
    portfinder.getPort((err, port) => {
        if (err) {
            reject(err)
        } else {
            // publish the new Port, necessary for e2e tests
            process.env.PORT = port
            // add port to devServer config
            devWebpackConfig.devServer.port = port

            // Add FriendlyErrorsPlugin
            devWebpackConfig.plugins.push(
                new FriendlyErrorsPlugin({
                    compilationSuccessInfo: {
                        messages: [
                            `Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`
                        ],
                        notes: []
                    },
                    clearConsole: true
                })
            )

            resolve(devWebpackConfig)
        }
    })
})
复制代码

文件拷贝

将public文件中的文件拷贝到dist文件下

yarn add copy-webpack-plugin -D
复制代码

这个功能只在打包的时候用到,所以我们在webpack.prod.conf.js中添加如下代码

const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpackConfig = merge(baseWebpackConfig, {
    //...
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                {
                    from: resolve('public'),
                    to: './',
                    globOptions: {
                        dot: true,
                        gitignore: true
                    }
                }
            ]
        })
        //...
    ]
})

复制代码

gzip/bundleAnalyzerReport

文件是否开启gzip压缩和是否生成打包报告,同样的只在打包的时候才用到
首先添加依赖

yarn add compression-webpack-plugin webpack-bundle-analyzer -D
复制代码

然后我们在webpack.prod.conf.js中添加如下代码

const config = require('./config')
const webpackConfig = merge(baseWebpackConfig,{//...})
if (config.build.productionGzip) {
    const CompressionWebpackPlugin = require('compression-webpack-plugin')

    webpackConfig.plugins.push(
        new CompressionWebpackPlugin({
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            test: new RegExp('\\.(' + config.build.productionGzipExtensions.join('|') + ')$'),
            threshold: 10240,
            minRatio: 0.8
        })
    )
}

if (config.build.bundleAnalyzerReport) {
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
    webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
复制代码

自动引入环境变量

在vue-cli中,我们可以在项目根目录中放置下列文件来指定环境变量

.env                # 在所有的环境中被载入
.env.local          # 在所有的环境中被载入,但会被 git 忽略
.env.[mode]         # 只在指定的模式中被载入
.env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略
复制代码

这个功能主要是通过dotenv这个包实现的,接下来我们也在项目中添加这个包

yarn add dotenv fs-extra -D
复制代码

在页面中添加loadEnvDefine方法

const fs = require('fs-extra')
const path = require('path')
exports.loadEnvDefine = (mode) => {
    const envDefine = {}
    if (fs.existsSync(`.env.${mode}`)) {
        require('dotenv').config({ path: `.env.${mode}` })
        const prefixRE = /^VUE_APP_/
        const envDefine = {}
        for (const key in process.env) {
            if (key == 'NODE_ENV' || key == 'BASE_URL' || prefixRE.test(key)) {
                envDefine[key] = JSON.stringify(process.env[key])
            }
        }
    }
    return envDefine
}
复制代码

webpack.base.conf.js文件中引入这个方法,并通过DefinePlugin注册到全局中

const { loadEnvDefine } = require('./utils')
const webpack = require('webpack')
module.exports = {
    //...
    plugins: [
        // ....,
        new webpack.DefinePlugin({
            'process.env': { ...loadEnvDefine(process.env.NODE_ENV) }
        })]
}
复制代码

总结

好了,我们的项目到这里可以说是搭建完成了,基本实现了vue-cli提供的大部分功能,如果大家有什么疑问或者建议,欢迎大家留言交流~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享