React+Webpack實現第三方庫和本身寫的代碼分開打包

背景

在項目中用webpack打包時,一般會將本身寫的業務邏輯代碼和第三方庫的js文件一塊兒打包成一個js文件,這樣的話這個文件就會很大,對項目的運行速率影響很大。並且,咱們在打包時每次都會將第三方庫文件從新打包一次,可是每每這樣是沒有必要的,由於第三方每每是不會發生很大改變的,只是可能會須要升級一下。因此在這裏,將第三方庫文件和本身寫的js文件分開打包仍是頗有必要的,這裏總結一下目前用得最多的兩種方法。css

利用react官網的腳手架建立一個例子

按照下面幾個步驟就能夠建立一個小demohtml

  • npm add create-react-app
  • create-react-app myapp
  • cd myapp
  • npm start

運行完這幾步後,恭喜你成功建立了一個react小例子,接下來須要作的就是如何使用webpack來打包這個demo。node

在myapp下建立webpack.base.config.js文件

在文件中寫基本的配置以下:react

const path = require('path')
const webpack = require('webpack')

function resolve(relatedPath) {
  return path.join(__dirname, relatedPath)
}
module.exports = {
  entry: {
    index: resolve('../myapp/src/index.js')
  },
  output: {
    path: resolve('../myapp/dist'),
    filename: '[name].[hash:4].js',
    chunkFilename: 'chunks/[name].[hash:4].js',
  },
  resolveLoader: {
    moduleExtensions: ['-loader']
  },
  module: {
    rules: [
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['react', 'es2015', 'stage-0']
        }
      },
      {
        test: /\.css/,
        loader: 'css'
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url',
        options: {
          limit: 8192,
          name: 'img/[name].[hash:4].[ext]'
        }
      },
      {
        test: /\.html$/,  //靜態資源
        loader: 'html',
      }
    ],
  }

}

package.json文件的配置內容以下:webpack

"dependencies": {
    "react": "^16.5.0",
    "react-dom": "^16.5.0",
    "webpack": "~3.10.0"
  },
  "devDependencies": {
    "babel-core": "~6.26.0",
    "babel-eslint": "~8.2.1",
    "babel-loader": "~7.1.2",
    "babel-plugin-import": "^1.8.0",
    "babel-plugin-transform-decorators-legacy": "~1.3.4",
    "babel-plugin-transform-runtime": "~6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "~0.28.9",
    "url-loader": "~0.6.2"
  }

使用npm install或yarn install就能夠將須要的工具都加載好web

修改package.json中scripts中的內容

在上面的package.json文件中將build的內容改爲npm

"build": "webpack --config webpack.base.config.js"

而後npm build和yarn build都可,這樣就使用webpack打包了react官網的例子json

分析

首先看一下這個小demo的文件目錄
圖片描述babel

本身的業務邏輯是src中的文件,而第三方庫是在node_modules中,咱們就須要將這兩個分開打包,由於node-modules相對於本身的js文件是很大的,下面介紹一下兩種分開打包的方法。app

使用CommonsChunkPlugin

這個方法會使咱們的第三方庫文件在打包的時候和本身的業務邏輯分開,也很簡單,主要是路徑要寫對,就像下面這樣在你的配置文件中添加便可

plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendors',
      filename: '[name].[hash:4].js'//生成的vendors文件就是以這樣的形式命名
    }),

  ]

在webpack.base.config.js的入口文件中增長

vendors: ['react', "react-dom"]//指的是想將什麼第三方文件庫進行分開打包

這樣就能夠實現分開打包的功能了,是否是很簡單,固然簡單一點,必然也是有缺點的,至於缺點是啥,就接着往下看咯!

使用DllPlugin

這個插件比CommonsChunkPlugin更復雜一些,固然也好一些,並且要配合.DllReferencePlugin使用,使用DllPlugin須要單首創建一個配置文件,咱們叫它webpack.dll.config.js文件,在這個文件中咱們須要放置這些內容:

const webpack = require('webpack')
const path = require('path')

function resolve(relatedPath) {
  return path.join(__dirname, relatedPath)
}

module.exports = {
  entry: {
    vendors: ['react', "react-dom"]//須要打包的第三方庫文件
  },

  output: {
    filename: '[name].[chunkhash:4].js',//生成的文件名
    path: resolve('../myapp/dist'),//生成的文件存放的路徑
    library: '[name]_[chunkhash:4]'//決定了manifest中的格式
  },

  plugins: [
    new webpack.DllPlugin({
      path: resolve('../myapp/dist/manifest.json'),
      name: '[name]_[chunkhash:4]',//生成的第三方庫文件, 要和上面的library一致
      context:__dirname
    }),
  ],
}

在webpack.dll.config.js放置這些事後還要在webpack.base.config.js中放置它的搭檔插件

plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,//上下文關係
      manifest: require('./dist/manifest.json')//生成的索引表
    }),
  ],

完成這兩步後要給package.json文件中scripts中的內容添加一條

"webpack": "webpack --config webpack.dll.config.js"

而後運行yarn webpack,再運行yarn build就能夠看到生成以下的文件目錄
圖片描述

生成了三個文件,本身寫的代碼打包後的是index.js,第三方是vendors.js,而manifest則是這兩個的橋樑,是用來聯繫index.js和vendors.js的。
圖片描述

點開文件夾你會發現js文件會變小不少,而vendors.js會大不少,這樣就是分離成功了。

總結

這兩個插件均可以實分開打包的功能,前者較後者比較簡單,後者比前者更高效,高效體如今後者是在編譯的過程就將二者分開了,便可以只編譯本身寫的代碼,也能夠調用vendors.js中的第三方庫;而前者是在打包的時候將二者分開,這樣看的話仍是後者更加高效。

相關文章
相關標籤/搜索