webpack4.x配置指南

簡介

鑑於webpack更新太快,總結下基礎配置方法,理解有限,僅作拋磚引玉之用。javascript

起步

初始化配置文件 package.json並安裝webpackcss

mkdir webpack-demo && cd webpack-demo
npm init -y    //-y 初始化選項默認爲 yes      
npm i webpack webpack-cli -D // -D 即 -save-dev    版本4.x以上須要安裝webpack-cli

建立如下目錄結構、文件和內容:html

webpack-demo
  |- package.json
+ |- /src
+   |- index.js
//index.js
document.write("Hello webpack4!");

建立webpack配置文件

編寫開發環境和生產環境彼此獨立的webpack配置文件
先添加三個文件java

webpack-demo
  |- package.json
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /src
    |- index.js
  |- /node_modules

1.webpack.common.jsnode

用到兩個基本的插件react

npm i clean-webpack-plugin html-webpack-plugin -D

clean-webpack-plugin:打包時自動清除輸出文件夾中未用到的文件;
html-webpack-plugin:打包時會自動生成index.html並替換已有的index.html,bundle.js也會自行添加到 html 中。webpack

//webpack.common.js
    const path = require('path');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');  
    const HtmlWebpackPlugin = require('html-webpack-plugin');    
    
    module.exports = {
      entry: './src/index.js',
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          title: 'index'
        })
      ],
      output: {
        filename: 'bundle.js',           
        path: path.resolve(__dirname, 'dist')    //定義輸出文件夾dist路徑
      }
    };

2.webpack.dev.jses6

先安裝webpack-merge,用以合併通用配置文件與開發環境配置文件web

npm i webpack-merge -D

安裝開發服務器devServer,做用是修改代碼後實時從新加載(刷新瀏覽器)npm

npm i webpack-dev-server -D
//webpack.dev.js
  const merge = require('webpack-merge');
  const common = require('./webpack.common.js');
  const webpack = require('webpack');
    
  module.exports = merge(common,{
     devServer: {                //啓用開發服務器
       contentBase: './dist',   //告訴服務器從哪提供內容,只有在想要提供靜態文件時才須要
       compress: true,          //一切服務都啓用gzip 壓縮
       host: '0.0.0.0',         //指定使用一個host,可用ip地址訪問,沒有的話若是別人訪問會被禁止。默認localhost。
       port: '9999',            //指定端口號,如省略,默認爲」8080「
       hot: true,               //啓用模塊熱替換特性
       inline: true,            //啓用內聯模式,一段處理實時重載的腳本被插入到bundle中,而且構建消息會出如今瀏覽器控制檯
       historyApiFallback: true,//開發單頁應用時有用,依賴於HTML5 history API,設爲true時全部跳轉將指向index.html
     },
     plugins: [
         new webpack.HotModuleReplacementPlugin(),  //webpack內置的熱更新插件
     ],
     mode: 'development'
  });

devServer的更多可選參數-https://www.webpackjs.com/con...

HotModuleReplacementPlugin 模塊熱替換(Hot Module Replacement)插件,用以在運行時更新發生改變的模塊,從而無需進行徹底刷新。

3.webpack.prod.js

一樣用'webpack-merge'合併通用配置文件與生產環境配置文件

//webpack.prod.js
  const merge = require('webpack-merge');
  const common = require('./webpack.common.js');
    
  module.exports = merge(common,{
    mode: "production"
  });
關於 mode

此時你可能會注意到配置文件中有個mode項,webpack4中新加,做用以下:

  • --mode production 生產環境

    不須要像舊版本同樣定義node環境變量
    new webpack.DefinePlugin({"process.env.NODE_ENV":JSON.stringify("production") })

    ps:許多 library 將經過與 process.env.NODE_ENV 環境變量關聯,以決定 library 中應該引用哪些內容。當使用 process.env.NODE_ENV === 'production' 時,一些 library 可能針對具體用戶的環境進行代碼優化,從而刪除或添加一些重要代碼。

    自動開啓一些插件,如:
    uglifyjs-webpack-plugin js代碼壓縮(因此無需再單獨使用)
    NoEmitOnErrorsPlugin 編譯出錯時跳過輸出,以確保輸出資源不包含錯誤
    ModuleConcatenationPlugin webpack3 添加的做用域提高(Scope Hoisting)

  • --mode development 開發環境

    自行定義node環境變量爲development
    new webpack.DefinePlugin({"process.env.NODE_ENV":JSON.stringify("development") })
    使用 eval 構建 module, 提高增量構建速度
    自動開啓一些插件,如
    NamedModulesPlugin 使用模塊熱替換(HMR)時會顯示模塊的相對路徑

具體描述:

Option Description
development Sets process.env.NODE_ENV to value development. Enables NamedChunksPlugin and NamedModulesPlugin.
production Sets process.env.NODE_ENV to value production. Enables FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin.
none Opts out of any default optimization options

啓動

package.json "scripts" 中添加npm腳本,從而快捷運行開發服務器 | 打包生產環境代碼

//package.json
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.19",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.15.1",
    "webpack-cli": "^3.0.8",
    "webpack-dev-server": "^3.1.4",
    "webpack-merge": "^4.1.3"
  }
}

"start": "webpack-dev-server --open --config webpack.dev.js",

webpack-dev-server    啓動開發服務器   
--open    打開瀏覽器
--config webpack.dev.js    設置運行此腳本時執行的配置文件爲webpack.dev.js

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

webpack 啓動webpack
--config webpack.prod.js   設置運行此腳本時執行的配置文件爲webpack.prod.js
執行 npm start

此時應該能夠看到 Hello webpack4!

執行 npm run build

項目文件夾中自動生成打包後的文件目錄(輸出文件夾dist)

webpack-demo
  |- package.json
  |- webpack.common.js
  |- webpack.dev.js
  |- webpack.prod.js
  |- /src
    |- index.js
  |- /dist 
      | - index.html
      | - app.bundle.js
  |- /node_modules

使用sourcemap

sourcemap 能實現打包後的運行代碼與源代碼的映射,幫助咱們debug到原始開發代碼。

///webpack.dev.js
  module.exports = merge(common,{
    devtool: 'cheap-module-eval-source-map',
    ...
  });

大多數時候開發環境用'cheap-module-eval-source-map'是最好的選擇,想要完整的功能又不介意構建速度的話就直接用'source-map'。具體的配置項不少,能夠是eval,source-map,cheap,module,inline的任意組合。
具體每一個參數的做用請查閱官方api:https://webpack.js.org/config...
也可參考這篇文章https://segmentfault.com/a/11... 這裏不作詳述。

代碼分離

把代碼分離到不一樣的 bundle 中,能夠按需加載或並行加載這些文件。可用於獲取更小的 bundle,以及控制資源加載優先級,若是使用合理,會極大影響加載時間。

三種經常使用的代碼分離方法:

1.入口起點:使用 entry 配置手動地分離代碼。

先在src文件夾添加一個文件another-module.js

//another-module.js
  import _ from 'lodash';
  console.log(
    _.join(['Another', 'module', 'loaded!'], ' ')
  );

修改index.js

//index.js
  import _ from 'lodash';
  console.log(
    _.join(['index', 'module', 'loaded!'], ' ')
  );

用到了lodash,安裝下依賴

npm i lodash -S

修改webpack.common.js中entry和output配置

//webpack.common.js
  module.exports = {
    entry: {
      index: './src/index.js',
      another: './src/another-module.js'
    },
    output: {
      filename: '[name].bundle.js',            //根據入口文件名來定義輸出文件名
      path: path.resolve(__dirname, 'dist')
    }
};
執行 npm run build

將生成以下構建結果:

Hash: 66f57fffc46778f3b145
Version: webpack 4.16.0
Time: 2966ms
            Asset       Size  Chunks             Chunk Names
another.bundle.js   70.4 KiB       0  [emitted]  another
  index.bundle.js   70.4 KiB       1  [emitted]  index
       index.html  251 bytes          [emitted]  
[1] (webpack)/buildin/module.js 497 bytes {0} {1} [built]
[2] (webpack)/buildin/global.js 489 bytes {0} {1} [built]
[3] ./src/another-module.js 86 bytes {0} [built]
[4] ./src/index.js 83 bytes {1} [built]
    + 1 hidden module
Child html-webpack-plugin for "index.html":
     1 asset
    [0] (webpack)/buildin/module.js 497 bytes {0} [built]
    [1] (webpack)/buildin/global.js 489 bytes {0} [built]
        + 2 hidden modules

存在的問題:

  • 若是入口 chunks 之間包含重複的模塊,那些重複模塊都會被引入到各個 bundle 中。
  • 不夠靈活,不能將核心應用程序邏輯動態地拆分代碼。

以上兩點中,第一點對咱們的示例來講無疑是個問題,index.js 和another-module.js中都引入了 lodash,這樣就在兩個 bundle 中形成重複引用。接着,咱們經過使用 SplitChunks 來移除重複的模塊。

2.防止重複:使用SplitChunks 去重和分離 chunk。webpack4 以前版本用的是CommonsChunkPlugin

//webpack.common.js
  const path = require('path');
  module.exports = {
    entry:  {
      index: './src/index.js',
      another: './src/another-module.js'
    },
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Production'
      })
    ],
    output: {
      filename: '[name].bundle.js',            //根據入口文件名來定義輸出文件名
      path: path.resolve(__dirname, 'dist')
    },
+   optimization: {
+     splitChunks: {
+       chunks: 'all'
+     }
+   }
  };
再次執行npm run build查看效果
...

vendors~another~index.bundle.js   69.5 KiB       0  [emitted]  vendors~another~index
              another.bundle.js   1.54 KiB       1  [emitted]  another
                index.bundle.js   1.54 KiB       2  [emitted]  index
                
...

觀察打包後文件大小,能夠看到index.bundle.jsanother.bundle.js中已經移除了重複的依賴模塊。lodash 被分離到單獨的vendors~another~index.bundle.jschunk中。

3.動態導入:經過模塊的內聯函數調用來分離代碼。
略~。~

分離css

須要用到插件mini-css-extract-plugin,這個插件會將提取css到單獨的文件,根據每一個包含css的js文件建立一個css文件,所以,你的樣式將再也不內嵌到 JS bundle 中。若是你的樣式文件大小較大,這會作更快提早加載,由於 CSS bundle 會跟 JS bundle 並行加載。同時還支持按需加載css和SourceMaps.

相較於舊版extract-text-webpack-plugin插件,mini-css-extract-plugin的優點有

  • 異步加載
  • 沒有重複的編譯
  • 更容易使用
  • Specific to CSS
  • 支持熱更新
npm i mini-css-extract-plugin -D
//webpack.common.js
  const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  module.exports = {
    ...
    plugins: [
      new MiniCssExtractPlugin({
        filename: "[name].css",
      })
    ],
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader,
              options: {
                publicPath: '../'             //能夠配置輸出的css文件路徑
              }
            },
            "css-loader"
          ]
        }
      ]
    }
    ...
  }

注意,這個插件不兼容style-loader (用於以<style>標籤形式將css-loader內部樣式注入到HTML頁面)。

若是想在開發環境下使用style-loader,在生產環境分離css文件,能夠這麼配置:

//webpack.common.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production'

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader:"postcss-loader",    //本文未用到此loader...
            options: {           // 若是沒有options這個選項將會報錯 No PostCSS Config found
                plugins: (loader) => []
            }
          },
          'sass-loader',
        ],
      }
    ]
  }
}

很明顯咱們須要先安裝處理樣式文件的各類loader

npm i style-loader css-loader postcss-loader node-sass sass-loader -D

這裏有個問題,node環境變量process.env.NODE_ENV在webpack.config中實際上是undefined,以前說起的mode配置會自動定義這個環境變量,但只能在打包後的js中取到,如何在webpack的配置文件中獲取這個值呢,須要引入cross-env

npm i cross-env -D

而後在package.json的腳本命令中指定環境變量

"start": "cross-env NODE_ENV=development webpack-dev-server --open --config webpack.dev.js",
"build": "cross-env NODE_ENV=production  webpack --config webpack.prod.js"

可自行添加css文件,在js中import,執行npm run build查看效果

固然也能夠不獲取process.env.NODE_ENV來區分環境,在dev.js和prod.js分別配置處理樣式文件的rule就好了,這也是最開始咱們分開寫開發環境和生產環境的webpack配置文件的緣由。這裏說起只是方便從低版本webpack遷移到4.x。

在單個文件中提取全部CSS
配合optimization.splitChunks.cacheGroups使用

//webpack.common.js
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        }
      }
    }
  }

會額外生成一個styles.bundle.js

按照入口JS來分離css

//webpack.common.js
...

function recursiveIssuer(m) {
  if (m.issuer) {
    return recursiveIssuer(m.issuer);
  } else if (m.name) {
    return m.name;
  } else {
    return false;
  }
}

module.exports = {
  entry:  {
    index: './src/index.js',
    another: './src/another-module.js'
  },

  ...

  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {                                //分離第三方庫
          test: /[\\/]node_modules[\\/]/,
          name: 'lodash',
          chunks: 'all'
        },
        indexStyles: {
          name: 'index',                        
          test: (m,c,entry = 'index') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
          chunks: 'all',
          enforce: true
        },
        otherStyles: {
          name: 'another',
          test: (m,c,entry = 'another') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,
          chunks: 'all',
          enforce: true
        }
      }
    }
  }
};

壓縮css

webpack5可能會內置CSS壓縮,webpack4須要使用像optimize-css-assets-webpack-plugin這樣的插件。有個問題是設置optimization.minimizer後,會覆蓋上文提到的mode配置項提供的默認值,所以須要同時使用JS壓縮插件UglifyJsPlugin

npm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
//webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.config.js');

const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(common,{
    mode: "production",
    optimization: {
        minimizer: [
          new UglifyJsPlugin({
            cache: true,
            parallel: true,
            sourceMap: true // set to true if you want JS source maps
          }),
          new OptimizeCSSAssetsPlugin({})
        ],
    }
});

緩存

咱們都知道瀏覽器獲取資源是比較耗費時間的,因此它會使用一種名爲 緩存 的技術。經過命中緩存,以下降網絡流量,使網站加載速度更快。若是咱們在部署新版本時不更改資源的文件名,瀏覽器就可能會認爲它沒有被更新,就會使用它的緩存版本。所以確保 webpack 編譯生成的文件可以被客戶端緩存,而在文件內容變化後,可以請求到新的文件是頗有必要的。

經過使用 output.filename 進行文件名替換,能夠確保瀏覽器獲取到修改後的文件。[hash]替換能夠用於在文件名中包含一個構建相關的hash,可是更好的方式是使用[chunkhash]替換,在文件名中包含一個 chunk相關的hash。遺憾的是chunkhash和熱更新不兼容,因此開發環境和生產環境要分開配置。

//webpack.common.js
  ...
  output: {
      filename: devMode ? '[name].[hash:8].js': '[name].[chunkhash:8].js',       //數字8表示取hash標識符的前八位
      chunkFilename: devMode ? '[name].[hash:8].js': '[name].[chunkhash:8].js',  //異步模塊的文件輸出名
      path: path.resolve(__dirname, 'dist')
  },
  ...

關於[hash][chunkhash]的區別,簡單來講,[hash]是編譯(compilation)後的hash值,compilation對象表明某個版本的資源對應的編譯進程。項目中任何一個文件改動,webpack就會從新建立compilation對象,而後計算新的compilation的hash值,全部的編譯輸出文件名都會使用相同的hash指紋,改一個就一塊兒變。而[chunkhash]是根據具體模塊文件的內容計算所得的hash值,某個文件的改動只會影響它自己的hash指紋,不會影響其餘文件。

上文代碼分離一節中已經提到了如何將第三方庫(好比lodash或react)提取到單獨的vendor chunk文件中,由於它們不多像本地的源代碼那樣頻繁修改。利用客戶端的長效緩存機制,能夠消除請求,減小向服務器獲取資源,同時還能保證客戶端代碼和服務器端代碼版本一致。
除了第三方庫,webpack在入口模塊中,包含了某些樣板(boilerplate),確切來講就是runtimemanifest。即webpack運行時的引導代碼,這部分代碼咱們也將它單獨提取出來。

//webpack.common.js
  ...
  optimization: {
    runtimeChunk: 'single',        //分離webpack運行時的引導代碼
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
  ...

咱們刪掉another-module.js,修改index.js以下

///index.js
import _ from 'lodash';

function component() {
    var element = document.createElement('div');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    return element;
}

document.body.appendChild(component());
執行npm run build

產生如下輸出:

Hash: 131e8681e4403392cb5d
Version: webpack 4.16.1
Time: 744ms
              Asset       Size  Chunks             Chunk Names
  index.5bc56cae.js  260 bytes       0  [emitted]  index
vendors.5d8f5a63.js   69.5 KiB       1  [emitted]  vendors
runtime.eb6eb2fb.js   1.42 KiB       2  [emitted]  runtime
         index.html  316 bytes          [emitted]  
[1] ./src/index.js 253 bytes {0} [built]
[2] (webpack)/buildin/global.js 489 bytes {1} [built]
[3] (webpack)/buildin/module.js 497 bytes {1} [built]
    + 1 hidden module
Child html-webpack-plugin for "index.html":
     1 asset
    [2] (webpack)/buildin/global.js 489 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 2 hidden modules

能夠看到編譯出的文件名後加上了hash,運行時的引導代碼也被單獨提取出來了。

接着添加一個print.js

///print.js
export default function print(text) {
   console.log(text);
};

修改index.js

///index.js
  import _ from 'lodash';
+ import Print from './print';

  function component() {
    var element = document.createElement('div');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+   element.onclick = Print.bind(null, 'Hello webpack!');

    return element;
  }

  document.body.appendChild(component());
再執行npm run build

構建結果以下:

Hash: a710a54674ea8d4b3263
Version: webpack 4.16.1
Time: 3328ms
              Asset       Size  Chunks             Chunk Names
  index.15466585.js  327 bytes       0  [emitted]  index
vendors.7bde7828.js   69.5 KiB       1  [emitted]  vendors
runtime.eb6eb2fb.js   1.42 KiB       2  [emitted]  runtime
         index.html  316 bytes          [emitted]  
[1] (webpack)/buildin/global.js 489 bytes {1} [built]
[2] (webpack)/buildin/module.js 497 bytes {1} [built]
[3] ./src/index.js + 1 modules 406 bytes {0} [built]
    | ./src/index.js 337 bytes [built]
    | ./src/print.js 64 bytes [built]
    + 1 hidden module
Child html-webpack-plugin for "index.html":
     1 asset
    [2] (webpack)/buildin/global.js 489 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 2 hidden modules

咱們指望的是,只有 index bundle 的 hash 發生變化,然而vendors也跟着變了。這是由於每一個 module.id 會基於默認的解析順序(resolve order)進行增量。也就是說,當解析順序發生變化,ID 也會隨之改變。(官方文檔裏說runtime的hash也發生了變化,這裏並未出現)
可使用兩個插件來解決這個問題。一是NamedModulesPlugin,將使用模塊的路徑而不是數字標識符。此插件有助於在開發過程當中輸出結果的可讀性,但執行時間會長一些。二是使用webpack內置插件HashedModuleIdsPlugin,推薦用於生產環境構建:

const webpack = require('webpack');
  ...
  module.exports = {
    ...
    plugins: [
      ...
      new webpack.HashedModuleIdsPlugin(),
      ...
    ],
    ...
  };

接下來,咱們能夠隨意修改index.js的代碼或者增刪print.js,再進行構建查看hash的變化。

關於css緩存
假如index.js引用了一個index.css文件,它們會共用相同的chunkhash值。這時若是index.js更改了代碼,index.css文件就算內容沒有任何改變也會重複構建。
咱們可使用MiniCssExtractPlugin裏的contenthash,保證css文件所處的模塊裏只要css文件內容不變,其自己就不會重複構建。

new MiniCssExtractPlugin({
  filename: "[name].[contenthash:8].css",
  chunkFilename: "[name].[contenthash:8].css"
}),

這樣基本就完成了webpack的緩存配置。

有個小問題是,當修改index.css文件代碼,從新構建後index.js的hash值也一塊兒改變了。。。
嘗試了下安裝插件WebpackMd5Hash能夠解決

npm i webpack-md5-hash -D

but,這個插件可能會引起別的bug,好吧這裏先不用,後續補充,有興趣可自行搜索

Babel

完成了基本的配置文件編寫與代碼分離,開發中須要用babel將舊的瀏覽器或環境中的es 2015+代碼轉換爲es5。
須要安裝一些依賴。

babel-core           //必備的核心庫
babel-loader         //webpack loader配置必備
babel-preset-env     //支持es201五、201六、2017,
babel-preset-stage-0 //默認向後支持 stage-1,stage-2,stage-3,
babel-runtime        
babel-plugin-transform-runtime //轉譯新的API
npm i babel-runtime -S
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-plugin-transform-runtime  -D

建立.babelrc文件

///.babelrc
{
  "presets": [
    "env",
    "stage-0"
  ],
  "plugins": [
    ["transform-runtime", {
      "helpers": false, //建議爲false
      "polyfill": false, //是否切換新的內置插件(Promise,Set,Map等)爲使用非全局污染的 polyfill,根據你的網站兼容性狀況來看,開啓會增長不少額外的代碼
      "regenerator": true //是否切換 generator 函數爲不污染全局做用域的 regenerator runtime。
    }],
  ]
}

關於 babel-polyfill 與 babel-plugin-transform-runtime

babel 能夠轉譯新的 JavaScript 語法,但並不會轉化BOM裏面不兼容的API好比Promise,Set,Symbol,Array.from,async 等。這時就須要 polyfill(軟墊片) 來轉化這些API

babel-polyfill會仿效一個完整的 ES2015+ 環境,這樣你就可使用新的內置對象好比 Promise 或WeakMap, 靜態方法好比 Array.from 或者 Object.assign, 實例方法好比 Array.prototype.includes 和生成器函數(提供 regenerator 插件)。babel-polyfill缺點是它經過改寫全局prototype的方式實現,會污染全局對象因此不適合第三方庫的開發,且打包後代碼冗餘量比較大,咱們可能不須要用到全部的新API,對於現代瀏覽器有些也不須要polyfill。

babel-plugin-transform-runtime 依賴babel-runtime,babel編譯es6到es5的過程當中,babel-plugin-transform-runtime會自動polyfill es5不支持的特性,這些polyfill包就是在babel-runtime這個包裏(這就是爲啥babel-runtime 須要做爲生產依賴引入(使用 --save))。transform-runtime優勢是不會污染全局變量,屢次使用只會打包一次,而且統一按需引入依賴,無重複、多餘引入。缺點是例如"foobar".includes("foo")等實例方法將不起做用。

React

以react開發爲例,若是是搭建新的項目,能夠直接安裝官方腳手架create-react-app或者使用阿里的開源ui框架 Ant Design
這裏僅僅提一下如何在webpack中配置react開發環境

npm install react react-dom -S

還須要安裝

babel-plugin-transform-decorators-legacy //支持修飾符語法 @connect
babel-preset-react   //解析react語法
react-hot-loader     //react熱更新須要在babelrc作配置
///.babelrc
  {
  "presets": [
    "env",
    "react",
    "stage-0"
  ],
  "plugins": [
    ["transform-runtime", {
      "helpers": false, //建議爲false
      "polyfill": false, //是否開始polyfill,根據網站兼容性決定是否開啓
      "regenerator": true 
    }],
    "react-hot-loader/babel",     //react熱更新插件
    "transform-decorators-legacy" //修飾符語法轉換插件
  ]
}

若是以前webpack-dev-server配置正確,這時只要把你的根組件標記爲熱導出,就能啓用react熱更新

///index.js
  import React from 'react';
  import { hot } from 'react-hot-loader';
     
  const App = () => <div>Hello World!</div>
     
  export default hot(module)(App);

別忘了配置babel-loader

///webpack.common.js
  module: {
      rules: [{
          test: /\.jsx?$/,
          use: 'babel-loader'
      }]
  }

未完待續,容老夫喝口水先...

相關文章
相關標籤/搜索