webpack5搭建vue3(三)根据环境拆分webpack配置

·  阅读 542

根据环境拆分webpack配置

  • 为什么需要拆分配置?
  • 如何拆分配置?
  • 为什么要拆分配置

由于我们日常开发的项目, 后期需要根据不同的环境打包,生成对应环境的包,所以我们需要不同环境的webpack配置,比如开发环境我们需要安装很多利于我们开发过程中的插件,loader等,但是生产环境下不需要这些东西,所以就不需要把这些开发过程用到的插件打包进去。

  • 如何拆分配置?

需要用到的插件 webpack-merge,合并配置。我们将不同环境的配置分隔开, dev => webpack.dev.config.js, prod => webpack.prod.config.js; 公用的配置文件叫做 webpack.base.config.js

目录结构

    build
    |    | ———— build.js   
    |    | ———— webpack.dev.config.js
    |    | ———— webpack.prod.config.js
    |    | ———— webpack.base.config.js
    |
    public
    |    | ———— index.html
    |    | ———— favicon.ico
    |
    src
    |    | ———— main.ts
    |    | ———— App.vue
复制代码

webpack.dev.config.js 开发环境的配置

然后我们写一下webpack.dev.config.js的配置, 用于开发时使用。

    const { merge } = require('webpack-merge')
    const webpack = require('webpack')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
    const portfinder = require('portfinder')
    const webpackBaseConfig = require('./webpack.base.config')
    const HOST = process.env.HOST || '0.0.0.0'
    const PORT = process.env.PORT || 8088
    portfinder.basePort = PORT
    // 以上插件均为最新版本
    
    function createNotifierCallback () {
        const notifier = require('node-notifier')
        return (serverity, errors) => {
            if (serverity !== 'error') return
            const error = errors[0]
            const filename = error.file && error.file.split('!').pop()
            notifier.notify({
                title: packageConfig.name,
                message: serverity + ':' + error.name,
                subtitle: filename || '',
                icon: path.join(__dirname, 'logo.png')
            })
        }
    }
    module.exports = env => {
        let devConfig = merge(webpackBaseConfig, {
            devServer: {
                host: '0.0.0.0',
                port: 8088,
                inline: true,
                open: false, // 是否启动项目之后自动打开浏览器运行
                hot: true, // 启动热更新
                noInfo: true, // 无webpack运行时的打包信息
                proxy: {}, // 代理
                historyFallBack: true // 用于路由设置为'hostory'模式,刷新404的问题
            },
            target: 'web', // 不设置不会启动热更新, websocket不会连接
            plugins: [
                new webpack.DefinePlugin({
                    "process.env.NODE_ENV": env
                }),
                new webpack.HotMoudleReplacementPlugin(),
                new HtmlWebpackPlugin({
                    template: 'index.html', // 你的index.html模板文件
                    title: 'webpack拆分配置', // 你的index.html的title
                    filename: 'index.html', // 打包输出的文件名称
                    inject: true, // 将打包的js全部插入到body的最底部
                    favicon: '' // 你的网页标签的图标
                })
            ]
        })
        return new Promise((resolve, reject) => {
            portfinder.getPort((err, port) => {
                if (err) {
                    reject(err)
                } else {
                    devConfig.devServer.port = port
                    devConfig.plugins.push(new FriendlyErrorsWebpackPlugin({
                        compliationSuccessInfo: {
                            quiet: true,
                            message: [`Your application is running here http://${devConfig.devServer.host}:${devConfig.devServer.port}`]
                        },
                        onErrors: env === 'development' ? createNotifierCallback() : undefined
                    }))
                    resolve(devConfig)
                }
            })
        })
    }
复制代码

webpack.prod.config.js 生产环境配置

接下来是 生产环境的配置 webpack.prod.config.js

const { merge } = require("webpack-merge")
const webpack = require('webpack')
const webpackBaseConfig = require('./webpack.base.config')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
// const OptimizeCssWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
// optimize-css-assets-webpack-plugin  与 css-minimizer-webpack-plugin 两者用途一样, 随便挑一个用就行
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = env => {
    console.log(process.env.NODE_ENV)
    return merge(webpackBaseConfig(env), {
        optimization: {
            runtimeChunk: {
                name: "runtime"
            },
            usedExports: true,
            minimize: true,
            minimizer: [new TerserWebpackPlugin({
                parallel: true
            }), new CssMinimizerWebpackPlugin()],
            splitChunks: {
                cacheGroups: {
                    defaultVendors: {
                        chunks: 'initial',
                        name: 'vendors',
                        test: /[\\/]node_modules[\\/]/,
                        priority: -10
                    },
                    common: {
                        name: 'common',
                        chunks: 'initial',
                        minChunks: 2,
                        priority: -20
                    }
                }
            }
        },
        plugins: [
            new webpack.DefinePlugin({
                "__VUE_OPTIONS_API__": false,
                "__VUE_PROD_DEVTOOLS__": false,
                "proccess.env.NODE_ENV": env
            }),
            new HtmlWebpackPlugin({
                title: '移动端',
                template: require('path').resolve('public/index.html'),
                filename: 'index.html',
                hash: true,
                inject: true,
                chunks: ['runtime', 'vendors', 'common', 'main']
            }),
            new CleanWebpackPlugin({
                cleanOnceBeforeBuildPatterns: ['**/*', 'dist']
            })
        ]
    })
}
复制代码

webpack.base.config.js 公共配置

最后是 公共配置, 也就是loader的配置,和一些公用的插件。webpack.base.config.js

const webpack = require('webpack')
const VueLoaderPlugin = require('vue-loader/dist/plugin').default
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const resolve = (file) => {
    return require('path').resolve(__dirname, '..' file)
}
module.exports = env => ({
    mode: env,
    devtool: env === 'development' ? 'inline-cheap-module-source-map' : 'source-map',
    entry: {
        main: resolve('src/main.js')
    },
    output: {
        filename: 'js/[name][contenthash].js',
        path: env === 'development' ? resolve('dist') : resolve('servers/dist'),
        publicPath: '/',
        chunkFilename: 'js/[name]/[name][contenthash:7].js'
    },
    resolve: {
        alias: {
            '@': utils.resolve('src')
        },
        extensions: [".ts", ".tsx", ".js", ".vue", ".json"]
    },
    performance: false,
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        ts: 'ts-loader',
                        tsx: 'babel-loader!ts-loader'
                    }
                }
            },
            {
                test: /\.js$/,
                include: utils.resolve('src'),
                use: [
                    'thread-loader',
                    'babel-loader'
                ]
            },
            {
                test: /\.ts$/,
                include: utils.resolve('src'),
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            transpileOnly: true,
                            appendTsSuffixTo: [/TS\.vue$/]
                        }
                    }
                ]
            },
            {
                test: /\.tsx$/,
                include: utils.resolve('src'),
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            transpileOnly: true,
                            appendTsSuffixTo: [/TSX\.vue$/]
                        }
                    }
                ]
            },
            {
                test: /\.(sc|c)ss$/,
                use: [
                  {
                    loader: MiniCssExtractPlugin.loader
                  },
                  {
                    loader: 'css-loader',
                    options: {
                      importLoaders: 2
                    }
                  }, {
                    loader: 'postcss-loader'
                  }, {
                    loader: 'sass-loader'
                  }
                ],
                sideEffects: true
            },
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        new MiniCssExtractPlugin({
            filename: env === 'development' ? '[name].css' : 'css/[name]-[contenthash:7].css',
            chunkFilename: env === 'development' ? '[name].css' : 'css/[name]-[contenthash:7].css'
        })
    ]
})
复制代码

最后我们还需要一个打包入口 build.js

  
const webpack = require('webpack')
const chalk = require('chalk')
const webpackProdConfig = require('./webpack.prod.config')
module.exports = new Promise((resolve, reject) => {
    let env = process.argv[2].match(/(NODE_ENV=\w+)/g)[0].split('=')[1]
    console.log('打包环境', env)
    webpack(webpackProdConfig(env), (err, stats) => {
        process.stdout.write(stats.toString({
            colors: true,
            modules: false,
            children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
            chunks: false,
            chunkModules: false
        }) + '\n\n')
    
        if (stats.hasErrors()) {
            reject(err)
            console.log(chalk.red('  Build failed with errors.\n'))
            process.exit(1)
        }
    
        console.log(chalk.cyan('  Build complete.\n'))
        console.log(chalk.yellow(
        '  Tip: built files are meant to be served over an HTTP server.\n' +
        '  Opening index.html over file:// won\'t work.\n' + new Date()
        ))
        resolve()
    })
})
复制代码

package.json 配置

{
    "scripts": {
    "serve": "cd servers && yarn dev",
    "dev": "webpack-dev-server --config build/webpack.dev.config.js  --env=development --progress",
    "build": "node build/build.js --env.NODE_ENV=production"
  },
}
复制代码

总结

根据这三篇文章, 差不多就可以自己手搭公司的项目进行开发了, 其他的可以添加dllPlugin啊,cache-loader啊等,这些优化项根据需要添加就好了,代码开发规范 eslint 自行配置就好,相信自己,你可以的。

github给个星吧大佬

分类:
前端
标签: