Webpack構建library時的踩坑經歷

背景

隨着組件化、模塊化意識地不斷加強,愈來愈多同窗開始構建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格式化後的了,代表其能夠在BrowserAMDCommonJS環境下都可以使用,而且觀察到ReactreactDOM依賴是直接引用進來的,說明打包時的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

深刻理解externals

聰明的webpack早已經幫咱們想好了這點,接下來咱們經過深刻externals參數來解決此問題。模塊化

咱們一般狀況下配置的externals參數爲字符串格式,其表達的意思爲在全局變量裏查找此變量,例如以下配置表明使用window.jQuery組件化

{
    jquery:'jQuery'
}

爲了支持不一樣環境下,使用不一樣的依賴,externals提供了object格式的配置,例如以下配置表名了在全局變量環境下使用ReactDOM變量,在其餘環境下使用react-dom對象ui

相關文章
相關標籤/搜索