webpack4 的 vue 打包配置

前言

      前端時間寫了個多入口的 webpack4 的配置 ( multiple_page_webpack ),後面新開了下目錄,將其改爲打包 vue 的配置

      本次 webpack4 的配置源碼:https://github.com/VintageLin/webpack4ForVue

改造過程

      1. 先將上篇文章中的 mutiple_page_webpack 的入口改成單一入口,刪除尋找入口文件的 js,取消對其的引用

      2. 刪除無用的文件,根據 webpack 的配置,入口放在 src 文件目錄下,目錄結構變爲如下圖

      3. 安裝 vue,vue-loader,vue-template-compiler,因爲要使用到 vue-router,所以也一併安裝

npm install -D vue-loader vue-template-compiler
npm install -S vue
npm install -S vue-router

      4. 安裝完後,配置 webpack4。按照 vue 官網的文檔做法

       然後增加 vue-loader 的配置,查閱官網可得:

      根據文檔,webpack 的通用配置改爲如下:

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const htmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, '../build'),
    filename: 'js/[name].[hash].js',
    chunkFilename: 'js/[name].js'
  },
  // 控制檯打印輸出配置
  stats: {
    entrypoints: false,
    chunks: false,
    children: false,
    chunkModules: true,
    modules: false
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.(jpg|jpeg|png|gif)$/,
        loader: 'url-loader',
        options: {
          name: 'images/[name].[hash].[ext]',
          limit: 10000
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader?cacheDirectory=true', 'eslint-loader']
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      }
    ]
  },
  resolve: {
    // 模塊別名,方便import
    alias: {
      '@': path.resolve(__dirname, '../src/'),
      'vue$': 'vue/dist/vue.esm.js'
    },
    // 自動解析擴展名
    extensions: ['.js', '.json', '.vue']
  },
  plugins: [
    // 頁面模板
    new VueLoaderPlugin(),
    new htmlWebpackPlugin({
      template: './src/index.html',
      chunks: './src/index.js'
    })
  ]
}

      開發環境 config.DEV.js 的配置如下:

const merge = require('webpack-merge')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const chalk = require('chalk')
const log = console.log

const webpackUniversalConfig = require('./webpack.config.js')
const CONSTANT = require('./config.CONSTANT')

const config = {
  mode: 'development',
  devServer: {
    compress: true,               // gzip壓縮
    port: CONSTANT.INITIAL_PORT,  // 端口
    hot: true,                    // hot reload
    overlay: true,                // 出現編譯器錯誤或警告時,在瀏覽器中顯示全屏覆蓋層
    stats: 'minimal',
    quiet: true,
    host: CONSTANT.HOST
  },
  devtool: 'source-map',
  plugins: [],
  module: {
    rules: [
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          'vue-style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                require('autoprefixer')
              ]
            }
          }
        ],
      }
    ]
  }
}

module.exports = new Promise((resolve, reject) => {
  // 端口查找
  portfinder.getPort({
    port: CONSTANT.INITIAL_PORT,           // 起始
    stopPort: CONSTANT.STOP_PORT           // 結束
  }, function (err, res) {
    if (err) {
      log(chalk.red('在當前設定的區間無可使用的端口!'))
      process.exit()
    } else {
      log(chalk.green('當前DEV可運行的端口:', res))
      config.devServer.port = res
      config.plugins.push(new FriendlyErrorsWebpackPlugin({
        compilationSuccessInfo: {
          messages: [`當前項目運行在 http://${CONSTANT.HOST}:${res}`]
        }
      }))
      // 合併設置
      const config_DEV = merge(config, webpackUniversalConfig)
      resolve(config_DEV)
    }
  })
})

       生產打包配置 config.PROD.js 如下: 

const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const merge = require('webpack-merge')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin')
const webpackUniversalConfig = require("./webpack.config.js")

const config = {
  mode: 'production',
  output: {
    // 公共目錄定位到當前文件夾下
    publicPath: './'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          'vue-style-loader',
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                require('autoprefixer')
              ]
            }
          }
        ],
      }
    ]
  },
  performance: {
    hints: false 
  },
  plugins: [
    // 每次打包前清空打包目標文件夾
    new CleanWebpackPlugin(),
    // 抽離css到單獨文件
    new MiniCssExtractPlugin({
      filename: 'css/[name].css?[hash]',
      chunkFilename: '[id].[hash].css',
      ignoreOrder: false
    })
  ],
  optimization: {
    minimizer: [
      // js壓縮
      new UglifyWebpackPlugin({
        parallel: 4
      }),
      // css壓縮
      new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css/,       // 需要優化壓縮的文件名
        cssProcessor: require('cssnano'),
        cssProcessorPluginOptions: {
          preset: ['default', { discardComments: { removeAll: true } }],
        },
        canPrint: true
      })
    ],
    // 代碼拆分
    splitChunks: {
      cacheGroups: {
        // 打包node_modules中的文件
        vendor: {
          name: "vendor",
          test: /[\\/]node_modules[\\/]/,
          chunks: "all",
          priority: 10
        }
      }
    }
  }
}

const config_PROD = merge(config, webpackUniversalConfig)
module.exports = config_PROD

發現的問題

       以上代碼是更正過的!在我剛改爲打包 vue 的配置的時候,發現了個問題,就是每次保存樣式的時候,樣式都不自動熱更新。在開發者工具中查看了之後,發現它引用了一個 css 文件,切控制檯顯示無任何模塊被更新,沒有請求最新的 css 文件。在以前使用 vue 腳手架生成的項目中,每次保存文件,都是熱更新的,也沒有去引用這種提取出來頁面的樣式的 css。

       解決辦法:

      發現增加了

      發現問題所在之處後,覺得應該是 mini-css-extract-plugin 惹的鍋,是它導致了樣式不能熱更新,導致新樣式沒有直接注入到js代碼中去。因爲熱更新只支持 js 的 module,也就是說必須轉換成js讀取的。

       觀察熱更新的文件內容,也可以發現熱更新內容中沒有 css 過來,都被打包到 css 文件中了,只能刷新頁面實現樣式最新。破案了!

      根據上面的發現,將 webpack.config.jsconfig.DEV.js 中的配置去除 mini-css-extract-plugin 相關的配置,啓動後,修改 vue 的文件並保存,發現熱更新的文件中有了最新的 css 樣式過來了。百度搜索了下解決辦法,目前就看到有人提到這個問題,也是類似的解決辦法,只不過他是 webpack3,需要去除的是 extract-text-webpack-plugin ,問題地址在此: https://segmentfault.com/q/1010000007574764 

       所以,在開發環境並不需要這個提取 css 到文件的插件,在打包到文件的時候才需要用到這個插件。

       基本上改造成 vue 的 webpack4 打包配置也就這麼搞定了,其他的就是 src 目錄下的 vue 對 vue-router 的使用或者 vuex 的使用了。 

       前後呼應,源碼在這:https://github.com/VintageLin/webpack4ForVue 歡迎大家指出錯誤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章