成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

怎樣寫一個能同時用于Node和瀏覽器的JavaScript包?

開發 前端
我在這個問題上見過很多困惑,即使是很有經驗的 JavaScript 開發者也可能難以把握其中的巧妙之處。因此我認為值得為它書寫一小段教程。

我在這個問題上見過很多困惑,即使是很有經驗的 JavaScript 開發者也可能難以把握其中的巧妙之處。因此我認為值得為它書寫一小段教程。

[[184498]]

我在這個問題上見過很多困惑,即使是很有經驗的 JavaScript 開發者也可能難以把握其中的巧妙之處。因此我認為值得為它書寫一小段教程。

假設你有一個 JavaScript 的模塊想要發布到 npm 上,它是同時適用于 Node 和瀏覽器的。但是請注意!這個特殊的模塊在 Node 版本和瀏覽器版本上的實現有著細微的區別。

這種情況出現得實在頻繁,因為在 Node 和瀏覽器間有著很多微小的環境差別。在這種情況下,可以用比較巧妙的方法來正確地實現,尤其是當你在嘗試著使用最小的 browser 包(bundle)來優化的時候。

讓我們構建一個 JS 包

因此讓我們來寫一個小的 JavaScript 包,叫做 base64-encode-string。它所做的只是接收一個字符串作為輸入,輸出其 base64 編碼的版本。

對于瀏覽器來說,這很簡單:我們只需要使用自帶的 btoa 函數:

  1. module.exports = function (string) { 
  2.   return btoa(string); 
  3. }; 

然而在 Node 里并沒有 btoa 函數。因此,作為替代,我們需要自己創建一個 Buffer,然后在上面調用 buffer.toString()

  1. module.exports = function (string) { 
  2.   return Buffer.from(string, 'binary').toString('base64'); 
  3. }; 

對于一個字符串,這兩者都應提供其正確的 base64 編碼版本,比如:

  1. var b64encode = require('base64-encode-string'); 
  2. b64encode('foo');    // Zm9v 
  3. b64encode('foobar'); // Zm9vYmFy 

現在我們只需要一些方法來檢測我們究竟是在瀏覽器上運行還是在 Node 上,好讓我們能保證使用正確的版本。Browserify 和 Webpack 都定義了一個叫 process.browser 的字段,它會返回 true(譯者注:即瀏覽器環境下),然而在 Node 上這個字段返回 false。所以我們只需要簡單地:

  1. if (process.browser) { 
  2.   module.exports = function (string) { 
  3.     return btoa(string); 
  4.   }; 
  5. else { 
  6.   module.exports = function (string) { 
  7.     return Buffer.from(string, 'binary').toString('base64'); 
  8.   }; 

現在我們只需要把我們的文件命名為 index.js,鍵入 npm publish,我們就完成了,對不對?好的吧,這個方法有效,但不幸的是,這種實現有一個巨大的性能問題。

因為我們的 index.js 文件包含了對 Node 自帶的 processBuffer 模塊的引用,Browserify 和 Webpack 都會自動引入 polyfill,來將它們打包進這些模塊。

對于這個簡單的九行模塊,我算了一下, Browserify 和 Webpack 會創建 一個壓縮后有 24.7KB 的包 (7.6KB min+gz)。對于這種東西,用掉的空間實在是太多,因為在瀏覽器里,只需要 btoa 就能表示這個。

“browser” 字段,我該如何愛你

如果你在 Browserify 或者 Webpack 文檔里找解決這個問題的提示,你可能最后會發現 node-browser-resolve。這是一個對于 package.json"browser" 字段的規范,可以被用于定義在瀏覽器版本構建時需要被換掉的東西。

使用這種技術,我們可以將接下來這段加入我們的 package.json

  1.   /* ... */ 
  2.   "browser": { 
  3.     "./index.js""./browser.js" 
  4.   } 

然后將函數分割成兩個不同的文件:index.jsbrowser.js

  1. // index.js 
  2. module.exports = function (string) { 
  3.   return Buffer.from(string, 'binary').toString('base64'); 
  4. }; 
  5.  
  6. // browser.js 
  7. module.exports = function (string) { 
  8.   return btoa(string); 
  9. }; 

有了這次改進以后,Browserify 和 Webpack 會給出 更加合理的包:Browserify 的包壓縮后是 511 字節(315 min+gz),Webpack 的包壓縮后是 550 字節(297 min+gz)。

當我們將我們的包發布到 npm 時,在 Node 里運行 require('base64-encode-string') 的人將得到 Node 版的代碼,在 Browserfy 和 Webpack 里跑的人會得到瀏覽器版的代碼。

對于 Rollup 來說,這就有點復雜了,但也不需要太多額外的工作。Rollup 用戶需要使用 rollup-plugin-node-resolve 并在選項里將 browser 設置為 true

對 jspm 來說,很不幸地,沒有對 “browser” 字段的支持,但是 jspm 用戶可以通過 require('base64-encode-string/browser') 或者 jspm install npm:base64-encode-string -o "{main:'browser.js'}" 來迂回地解決問題。另一種方法是,包的作者可以在他們的 package.json指定一個 “jspm” 字段

進階技巧

這種直接使用的 "browser" 方法可以工作得很好,但是對于大型項目來說,我發現它在 package.json 和代碼庫間引入了一種尷尬的耦合。比如說,我們的 package.json 會很快長成這樣:

  1.   /* ... */ 
  2.   "browser": { 
  3.     "./index.js""./browser.js"
  4.     "./widget.js""./widget-browser.js"
  5.     "./doodad.js""./doodad-browser.js"
  6.     /* etc. */ 
  7.   } 

在這種情況下,任何時候你想要一個適配于瀏覽器的模塊,都需要分別創建兩個文件,并且要記住在 "browser" 字段上添加額外行來將它們連接起來。還要注意不能拼錯任何東西!

并且,你會發現你在費盡心機地將微小的代碼提取到分離的模塊里,僅僅是因為你想要避免 if (process.browser) {} 檢查。當這些 *-browser.js 文件積累起來的時候,它們會開始讓代碼庫變得很難跳轉。

如果這種情況變得實在太笨重了,有一些別的解決方案。我自己的偏好是使用 Rollup 作為構建工具,來自動地將單個代碼庫分割到不同的 index.jsbrowser.js 文件里。這對于將你提供給用戶的代碼的解模塊化有額外的價值,節省了空間和時間

要這樣做的話,先安裝 rolluprollup-plugin-replace,然后定義一個 rollup.config.js 文件:

  1. import replace from 'rollup-plugin-replace'
  2. export default { 
  3.   entry: 'src/index.js'
  4.   format: 'cjs'
  5.   plugins: [ 
  6.     replace({ 'process.browser': !!process.env.BROWSER }) 
  7.   ] 
  8. }; 

(我們將使用 process.env.BROWSER 作為一種方便地在瀏覽器構建和 Node 構建間切換的方式。)

接下來,我們可以創建一個帶有單個函數的 src/index.js 文件,使用普通的 process.browser 條件:

  1. export default function base64Encode(string) { 
  2.   if (process.browser) { 
  3.     return btoa(string); 
  4.   } else { 
  5.     return Buffer.from(string, 'binary').toString('base64'); 
  6.   } 

然后將 prepublish 步驟添加到 package.json 內,來生成文件:

  1.   /* ... */ 
  2.   "scripts": { 
  3.     "prepublish""rollup -c > index.js && BROWSER=true rollup -c > browser.js" 
  4.   } 

生成的文件都相當直白易讀:

  1. // index.js 
  2. 'use strict'
  3.  
  4. function base64Encode(string) { 
  5.   { 
  6.     return Buffer.from(string, 'binary').toString('base64'); 
  7.   } 
  8.  
  9. module.exports = base64Encode; 
  10.  
  11. // browser.js 
  12. 'use strict'
  13.  
  14. function base64Encode(string) { 
  15.   { 
  16.     return btoa(string); 
  17.   } 
  18.  
  19. module.exports = base64Encode; 

你將注意到,Rollup 會按需自動地將 process.browser 轉換成 true 或者 false,然后去掉那些無用代碼。所以在生成的瀏覽器包里不會有對于 process 或者 Buffer 的引用。

使用這個技巧,在你的代碼庫里可以有任意個的 process.browser 切換,并且發布的結果是兩個小的集中的 index.jsbrowser.js 文件,其中對于 Node 只有 Node 相關的代碼,對于瀏覽器只有瀏覽器相關的代碼。

作為附帶的福利,你可以配置 Rollup 來生成 ES 模塊構建,IIFE 構建,或者 UMD 構建。如果你想要示例的話,可以查看我的項目 marky,這是一個擁有多個 Rollup 構建目標的簡單庫。

在這篇文章里描述的實際項目(base64-encode-string)也同樣被 發布到 npm 上 ,你可以審視它,看看它是怎么做到的。源碼 在 GitHub 上

 

責任編輯:張燕妮 來源: 開源中國社區
相關推薦

2012-08-14 10:44:52

解釋器編程

2017-12-14 15:45:02

2021-06-02 06:14:50

Nyxt瀏覽器

2012-09-03 10:24:16

果粉瀏覽器

2009-05-27 08:54:15

瀏覽器平臺Chrome

2019-12-02 13:46:35

瀏覽器前端開發

2017-01-05 09:07:25

JavaScript瀏覽器驅動

2011-04-14 15:55:35

WPF.NET

2022-06-20 09:01:56

Plasmo開源

2020-07-06 08:23:11

開源瀏覽器操作系統

2022-06-13 06:33:04

瀏覽器瀏覽器插件

2014-08-18 14:58:25

微軟IE

2016-10-09 08:38:01

JavaScript瀏覽器事件

2012-01-04 13:55:23

Canvas

2020-03-12 11:29:51

JavaScript瀏覽器語言

2021-12-13 12:56:26

Linux瀏覽器

2012-04-25 14:06:45

HTML5

2023-01-18 14:16:16

lnavLinux瀏覽器

2021-08-06 16:52:10

瀏覽器HTTPS通信

2022-01-04 21:36:33

JS瀏覽器設計
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩色视频 | 欧美三级在线 | 波多野结衣中文视频 | 国产线视频精品免费观看视频 | 国产999精品久久久 精品三级在线观看 | 成人福利网 | 亚洲一区二区在线播放 | 国产一区二区三区四区hd | 国产欧美日韩综合精品一区二区 | 国产日韩欧美一区 | 精品成人免费视频 | 国产精品久久久av | 久久久www成人免费精品张筱雨 | 亚洲一区二区精品视频 | 日韩一区二区在线免费观看 | 91直接看| 欧美一级黄色网 | 欧美视频精品 | 欧美在线播放一区 | 免费h视频 | 中文字幕一区二区在线观看 | 精品一区二区观看 | 男人视频网站 | 久久久久久久一区 | 日本精品久久 | 亚洲一区二区视频 | 国产91精品久久久久久久网曝门 | 欧美一区二区在线观看视频 | 一级毛片在线播放 | 福利一区在线观看 | 中文字幕在线观看第一页 | 亚洲精品乱码 | 久久高清免费视频 | 精品美女| 成人国产免费观看 | 国产在线精品一区二区三区 | 精品欧美乱码久久久久久1区2区 | 日韩影院一区 | 完全免费av在线 | 欧美成人激情 | 精品国产网 |