Split the WebPack configuration based on the environment

  • Why do YOU need to split the configuration?
  • How do I split the configuration?
  • Why split the configuration

Since our daily development projects need to be packaged and generated according to different environments in the later stage, we need webpack configuration of different environments. For example, in the development environment, we need to install many plug-ins and loaders that are beneficial to our development process, but these things are not needed in the production environment. So there is no need to package these plug-ins for the development process.

  • How do I split the configuration?

The plugin webpack-merge is needed to merge the configuration. We separate the configurations for different environments, dev => webpack.dev.config.js, prod => webpack.prod.config.js; The common configuration file is called webpack.base.config.js

The directory structure

Build | | - build. Js | | -- - webpack. Dev. Config. Js | | -- - webpack. Prod. Config. Js | | -- - webpack. Base. Config. Js | Public | | -- - index. HTML | | -- - the favicon. Ico | SRC | | -- - main. Ts | | -- - App. VueCopy the code

Configuration of the webpack.dev.config.js development environment

Then let’s write the webpack.dev.config.js configuration for development use.

    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
    // The above plug-ins are of the latest version
    
    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.// Whether to automatically open the browser after starting the project
                hot: true.// Start hot update
                noInfo: true.// No packaging information for the WebPack runtime
                proxy: {}, / / agent
                historyFallBack: true // Refresh 404 problem with route set to 'hostory' mode
            },
            target: 'web'.// If not set, hot update will not start and webSocket will not connect
            plugins: [
                new webpack.DefinePlugin({
                    "process.env.NODE_ENV": env
                }),
                new webpack.HotMoudleReplacementPlugin(),
                new HtmlWebpackPlugin({
                    template: 'index.html'.// Your index.html template file
                    title: 'WebPack split configuration'.// The title of your index.html
                    filename: 'index.html'.// Package the output file name
                    inject: true.// Insert all the packed js files at the bottom of the body
                    favicon: ' ' // The icon of your webpage TAB})]})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)
                }
            })
        })
    }
Copy the code

Webpack.prod.config.js Production environment configuration

Next comes the configuration for the production environment, 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 and CSs-minimizer-webpack-plugin are the same, just choose one of them
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: 'Mobile end'.template: require('path').resolve('public/index.html'),
                filename: 'index.html'.hash: true.inject: true.chunks: ['runtime'.'vendors'.'common'.'main']}),new CleanWebpackPlugin({
                cleanOnceBeforeBuildPatterns: ['* * / *'.'dist']})]})}Copy the code

Webpack.base.config.js common configuration

Finally, there is the common configuration, that is, the loader configuration, and some common plug-ins. 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: {
            The '@': 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'})]})Copy the code

Finally, we need a package entry called 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('Package environment', 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()
    })
})
Copy the code

Package. The json configuration

{
    "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"}},Copy the code

conclusion

According to these three articles, you can almost take the company’s own project development, other can add dllPlugin, cache-loader, etc., these optimizations according to the need to add good, code development specification ESLint self-configure good, believe yourself, you can.

Give github a star bar