webpack踩坑記——DllPlugin和DllReferencePlugin

場景描述:

使用vue-cli官方提供的webpack項目,進行釘釘移動端的開發,項目中期遇到文件限制大小的問題,釘釘要求一個js不能超過5MB,而npm run dev的時候,並不會把app.js進行拆分,因此全部的依賴庫都在app.js裏,太大了。
因而就有了這個需求————在dev環境裏,也把依賴庫拆出來。javascript

方案一:

npm run build裏的方法拷貝過來,其實就是CommonsChunkPlugincss

原配置裏的寫法是把node_modules裏的庫都打包到vendor.js裏,這個方法裏能夠本身配置,返回個布爾值就能夠了。
拷貝過來之後,發現app.js是變小了,可是vendor.js巨大,5.2mb,仍是超了,並且,理論上這些庫(vue全家桶、mint、g2)加起來也不該該這麼大呀。html

方案二:

把依賴的庫,先總體都不做處理地打包出來,剩餘本身的app.js仍是該怎麼樣怎麼樣,webpack給咱們提供了這麼個插件DllPluginvue

新建一個配置文件,好比build/webpack.dll.conf.jsjava

const path = require('path')
const webpack = require('webpack')
module.exports = {
  entry: {
    vendor: ['vue','vue-router']
  },
  output: {
    path: path.join(__dirname, '../static'),
    filename: 'dll.[name].js',
    library: '[name]'
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '../', '[name]-manifest.json'),
      name: '[name]'
    })
  ]
}

entry裏就是先打包出來的庫,output就是輸出地址和名字,輸出到static,由於原配置已經會把static裏的內容直接複製到dist裏,就不去折騰改其餘地方了。
Dllplugin裏的path,會輸出一個vendor-manifest.json,這是用來作關聯id的,打包的時候不會打包進去,因此不用放到static裏
而後運行一下webpack -p --progress --config build/webpack.dll.conf.js
成功之後,static下會有dll.vendor.js,根目錄下會有vendor.manifest.json
各自打開看一下,就會看到依賴庫的源碼和匹配idnode

ok,到這裏,抽離依賴庫的事情就完成了,那麼接下來問題就是怎麼引用呢,怎麼在dev和build跑呢?webpack

這裏補了一點dll和commonsChunk概念上的區別,commonsChunk之因此慢和大,是由於每次run的時候,都會去作一次打包,而實際上咱們不會一直去更新咱們引用的依賴庫,因此dll的作法就等因而,事先先打包好依賴庫,而後只對每次都修改的js作打包。git

繼續剛纔的步驟

修改build/webpack.base.conf.js,添加DllReferencePlugin的配置github

const manifest = require('../vendor-manifest.json')
。。。。
plugins: [
    new webpack.DllReferencePlugin({
      manifest
    })
  ]

而後咱們直接打開index.html,在底部加上<script src="./static/dll.vendor.js"></script>
是的,就是這麼簡單粗暴。
運行一下npm run dev,打開f12看看網絡監控,一切順利的話,這樣就ok了web

接下來是打包,只須要把原來的commonsChunkPlugin的東西刪掉就能夠了。
npm run build --report
能夠感覺到速度比原來快了不是一點點

繼續優化

  1. 依賴從package.json讀取,而不是手寫;
  2. 帶上hash,以避免線上緩存問題;
  3. 帶上hash後,自動修改index.html裏的引用;
  4. 命令太長了,最好yarn run一下就行了
const path = require('path')
const webpack = require('webpack')
const package = require('../package.json')
const AssetsPlugin = require('assets-webpack-plugin')
//讀取package.json裏的依賴,normalize.css除外,打包會報錯
const package = require('../package.json')
let dependencies = Object.keys(package.dependencies) || []
//若是使用了chrome的vue-devtool,那打包的時候把vue也排除掉,由於壓縮過的vue是不能使用vue-devtool的
dependencies = dependencies.length > 0 ? dependencies.filter(item => item !== 'vue') : []

module.exports = {
  entry: {
    vendor: dependencies
  },
  output: {
    path: path.join(__dirname, '../static'),
    filename: 'dll.[name]_[hash:6].js',
    library: '[name]_[hash:6]'
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '../', '[name]-manifest.json'),
      name: '[name]_[hash:6]'
    }),
    new AssetsPlugin({
      filename: 'bundle-config.json',
      path: './'
    })
  ]
}

在build文件夾新建一個dll.js,讀一下配置,跑一下webpack,輸出點日誌。

var ora = require('ora')
var chalk = require('chalk')
var webpack = require('webpack')
var webpackConfig = require('./webpack.dll.conf')

var spinner = ora('building for dependencies...')
spinner.start()

webpack(webpackConfig, function (err, stats) {
  spinner.stop()
  if (err) throw err
  process.stdout.write(stats.toString({
    colors: true,
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false
  }) + '\n\n')

  console.log(chalk.cyan('  Build complete.\n'))
})

保存之後,到package.json裏添加命令,"dll": "node build/dll.js"
運行 yarn dll 完成~

代碼不在這裏贅述,能夠看個人 github

總結

沒有最好的配置,只有最適合的,遇到問題,思考問題,解決問題

參考

  1. https://doc.webpack-china.org...
  2. http://engineering.invisionap...
  3. https://segmentfault.com/a/11...
相關文章
相關標籤/搜索