隨着組件化、模塊化意識地不斷加強,愈來愈多同窗開始構建npm
包來供業務複用了。今天收到一位同窗的反饋,問題是構建出的package在使用時,會拋出ReactDOM找不到的異常,後來經過查看構建出的源碼,結合webpack
打包原理,找到了解決方案。react
首先,咱們回顧一下案發現場。jquery
Can't resolve 'ReactDOM' in xxxx
咱們繼續勘察,打開構建好的文件,源碼頭部以下所示:webpack
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("React")); else if(typeof define === 'function' && define.amd) define("module", ["React"], factory); else if(typeof exports === 'object') exports["module"] = factory(require("React")); else root["module"] = factory(root["React"]); })
咱們可以看到,頭部的腳本已是umd
格式化後的了,代表其能夠在Browser
、AMD
、CommonJS
環境下都可以使用,而且觀察到React
及reactDOM
依賴是直接引用進來的,說明打包時的externals
的確是設置過的,並且設置頗有可能以下:web
{ 'react':'React', 'react-dom':'ReactDOM' }
打包格式和資源抽離已經作好,爲何還會出錯呢?仔細觀察錯誤,webpack
報錯ReactDOM
依賴找不到,咱們嘗試將其引用的代碼遷移到項目裏,編寫以下:npm
const ReactDOM = require('ReactDOM');
可是在真實業務代碼裏,require的不是ReactDOM
,而是react-dom
,只是在構建的時候,將設置爲externals
裏的依賴進行替換而已。瀏覽器
恍然大悟,咱們意識到在CommonJS
下引入的依賴名應該爲react-dom
,而非瀏覽器環境下注入在全局變量裏的ReactDOM
,:故只須要千方百計將打包好的文件頭部裏對CommonJS環境下的依賴名進行修改成react-dom便可。dom
聰明的webpack早已經幫咱們想好了這點,接下來咱們經過深刻externals
參數來解決此問題。模塊化
咱們一般狀況下配置的externals
參數爲字符串格式,其表達的意思爲在全局變量裏查找此變量,例如以下配置表明使用window.jQuery
。組件化
{ jquery:'jQuery' }
爲了支持不一樣環境下,使用不一樣的依賴,externals
提供了object
格式的配置,例如以下配置表名了在全局變量環境下使用ReactDOM
變量,在其餘環境下使用react-dom
對象ui