webpack4.29.x成神之路(十四) 區分開發和生產環境

目錄css

上節: 搖樹優化(tree shaking)html

上節目錄以下:node

clipboard.png

環境介紹

webpack的mode選項有三個值:development | production | none, 分別看下不一樣模式下webpack的默認配置:webpack

clipboard.png

詳細參考:https://webpack.js.org/config...web

從默認配置也能夠看出,開發和生產模式下的配置很不同,因此是有必要給開發和生產環境分別寫一份配置。npm

開始

如今webpack.config.js的內容大概是這樣的:segmentfault

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'bundles')
  },

  // 開啓devServer
  devServer: {},

  
  // optimization: {
  //   // production模式下默認開啓
  //   usedExports: true
  // },

  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(gif|jpg|jpeg|png|svg)$/,
      use: ['url-loader']
    }, {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    }),
    new CleanWebpackPlugin()
  ]
};

根目錄下新建一個目錄webpack, 並將webpack.config.js複製兩份到該目錄下,
重命名爲webpack.dev.js和webpack.prod.js,目錄以下:babel

clipboard.png

先來寫開發環境下的配置,
webpack/webpack.dev.js:less

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: '[name].js',
    path: resolve(__dirname, '../bundles')
  },

  devtool: 'cheap-module-eval-source-map',

  // 開啓devServer
  devServer: {},


  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(gif|jpg|jpeg|png|svg)$/,
      use: ['url-loader']
    }, {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ]
};

生產環境下的配置,
webpack/webpack.prod.js:webpack-dev-server

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const { resolve } = require('path');
module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[contenthash:10].js',
    path: resolve(__dirname, '../bundles')
  },

  devtool: 'cheap-module-source-map',

  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(gif|jpg|jpeg|png|svg)$/,
      use: ['url-loader']
    }, {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    }),
    new CleanWebpackPlugin()
  ]
};

開發環境去掉了CleanWebpackPlugin,postcss-loader
生產環境去掉了devServer
而且都設置了不一樣devtool和output.filename

而後修改package.js的scripts屬性:

"scripts": {
    "dev": "webpack-dev-server --config webpack/webpack.dev.js",
    "build": "webpack --config webpack/webpack.prod.js"
  },

由於配置文件的名稱和路徑都變了,因此要用--config來指定
這時npm run build或npm run dev一切正常,配置也已區分。

抽離公共配置

如今兩種模式下的配置文件有不少的是相同的,咱們須要把它們抽離出來。
新建webpack/webpack.base.js,並把公共配置添加進去。
webpack/webpack.base.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: resolve(__dirname, '../bundles')
  },


  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(gif|jpg|jpeg|png|svg)$/,
      use: ['url-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ]
};

// 而後把webpack.dev.js和webpack.prod.js裏的公共代碼刪除。
webpack/webpack.dev.js:

module.exports = {
  mode: 'development',
  output: {
    filename: '[name].js'
  },
  devtool: 'cheap-module-eval-source-map',

  // 開啓devServer
  devServer: {},

  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader']
    }]
  }
};

webpack/webpack.prod.js:

const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
  mode: 'production',
  output: {
    filename: '[name].[contenthash:10].js'
  },

  devtool: 'cheap-module-source-map',

  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
    }]
  },
  plugins: [
    new CleanWebpackPlugin()
  ]
};

而後用webpack-merge插件把webpack.base.js合併到webpack.dev.js和webpack.prod.js裏去.

繼續修改配置
webpack/webpack.dev.js:

const merge = require('webpack-merge');
const baseConfig = require('./webpack.base');
module.exports = merge(baseConfig, {
  mode: 'development',
  output: {
    filename: '[name].js'
  },
  devtool: 'cheap-module-eval-source-map',

  // 開啓devServer
  devServer: {},

  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader']
    }]
  }
});

merge函數返回合併後的配置對象,webpack.prod.js也同樣:

const CleanWebpackPlugin = require('clean-webpack-plugin');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base');
module.exports = merge(baseConfig, {
  mode: 'production',
  output: {
    filename: '[name].[contenthash:10].js'
  },
  devtool: 'cheap-module-source-map',
  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
    }]
  },
  plugins: [
    new CleanWebpackPlugin()
  ]
});

而後安裝:npm i webpack-merge -D
裝完後再試下npm run dev和npm run build,效果應該仍是正常的。

環境變量

到目前爲止,區分配置其實已經完成,根目錄下的webpack.config.js已經能夠刪了,但咱們常常會看到不少人在一個文件中就作到區分配置,這裏就須要用到環境變量。這裏只介紹這種方式的作法,後續並不會用這種方式。
好比我只想用webpack.config.js這一個配置文件,那麼能夠這麼寫:
webpack.config.js:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const merge = require('webpack-merge');

const baseConfig = {
  entry: './src/index.js',
  output: {
    filename: '[name].js',
    path: resolve(__dirname, './bundles')
  },


  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(gif|jpg|jpeg|png|svg)$/,
      use: ['url-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './index.html'
    })
  ]
};



const devConfig = {
  mode: 'development',
  output: {
    filename: '[name].js'
  },
  devtool: 'cheap-module-eval-source-map',

  // 開啓devServer
  devServer: {},

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

const prodConfig = {
  mode: 'production',
  output: {
    filename: '[name].[contenthash:10].js'
  },
  devtool: 'cheap-module-source-map',
  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
    }]
  },
  plugins: [
    new CleanWebpackPlugin()
  ]
}

module.exports = env => {
  return env === 'development' ? merge(baseConfig, devConfig) : merge(baseConfig, prodConfig);
}

最後導出的配置取決於env的值,這個值在命令行中設置,好比:
運行開發環境:npx webpack-dev-server --env development
運行生產環境:npx webpack-dev-server --env production

若是配置過於複雜,還能夠將loader或plugin單獨分離出去

下節:代碼分割(code spliting)上

相關文章
相關標籤/搜索