<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          1.3 萬 Star!直接在瀏覽器端組織 JS 代碼的魔法工具

          共 4645字,需瀏覽 10分鐘

           ·

          2020-12-29 09:12

          【導(dǎo)語】:Browserify 是一個(gè)開源的 JS?編譯工具,可以讓你使用類似于 node 的 require() 的方式來組織瀏覽器端的 JS?代碼,通過預(yù)編譯讓前端 JS?可以直接使用 Node NPM 安裝的一些庫。

          簡介

          Browserify 是一個(gè)開源的?JavaScript 工具,它可以讓你像在 node 中那樣,在瀏覽器中也可以使用?require('module')?來加載模塊。換句話說,它可以讓服務(wù)端的 CommonJs 的模塊運(yùn)行在瀏覽器端。

          browserify-logo

          開源地址

          Browserify 在 GitHub 上已有 13.5k Star。

          https://github.com/browserify/browserify

          安裝

          如果你想在命令行中使用,可以直接全局安裝:

          npm?install?-g?browserify

          基礎(chǔ)使用

          簡單上手

          我們先來看一個(gè)簡單的例子。假設(shè)我們有一個(gè)文件 index.js,引入了一個(gè)外部模塊?uniq。首先我們安裝這個(gè)模塊

          npm?install?uniq

          接著在 index.js 使用這個(gè)模塊

          const?uniq??=?require("uniq");

          console.info(uniq([1,2,3,1,2,3]))

          我們知道,這個(gè) index.js 文件是可以直接在 node 環(huán)境下運(yùn)行的,但是在瀏覽器上運(yùn)行會有什么效果呢?

          我們來試一下效果,在 index.html 中手動引入這個(gè)文件:

          <script?src="./index.js">script>

          打開網(wǎng)頁,我們可以看到控制臺報(bào)錯(cuò)了:

          no-require-error

          其實(shí)很容易理解,我們根本沒有定義這個(gè)?require,瀏覽器當(dāng)然也不會認(rèn)識它了。這時(shí)候我們的主角 Browserify 就派上用場了,我們在當(dāng)前路徑下執(zhí)行如下命令:

          browserify?index.js?>?app.js

          然后修改我們 index.html 引入的腳本為 app.js:

          <script?src="./app.js">script>

          接著,我們刷新一下頁面,可以看到正常顯示了去重后的數(shù)組:

          外部依賴

          如果你想在 script 標(biāo)簽中直接使用第三方模塊,或者我們自己定義的模塊,你可以使用?--require?選項(xiàng)參數(shù),它的簡寫為?-r。

          承接上例,假設(shè)我們的 index.js 導(dǎo)出了一個(gè)對象:

          module.exports?=?{
          ??name:?"Jerry",
          ??techs:?["Vue",?"React",?"Webpack",?"Vue"]
          }

          并且我們想在 index.html 中直接使用 uniq 模塊和 index.js 導(dǎo)出的對象。此時(shí)我們需要修改我們的命令:

          browserify?-r?uniq?-r?index.js:myModule?>?app.js

          上述命令的意思是,將 uniq 打包成一個(gè)可 require 的模塊,將 index.js 也打包成一個(gè)可 require 的模塊,并且這個(gè)模塊的名字叫 myModule。

          接著在 index.html 中修改 script 標(biāo)簽:

          <script?src="./app.js">script>
          <script>
          ??const?uniq??=?require("uniq");
          ??const?myModule?=?require("myModule");
          ??console.info(`Got?unique?techs?[${uniq(myModule.techs)}]?from?${myModule.name}`)

          script>
          externals

          可以看到,輸出內(nèi)容跟我們預(yù)期的一致。

          生成 sourcemap

          Browserify 也可以生成 sourcemap 方便我們開發(fā)中定位問題,它的使用很簡單,只需要加上?--debug?選項(xiàng)即可(簡寫為?-d)。我們修改之前的命令:

          browserify?-d?-r?uniq?-r?index.js:myModule?>?app.js?

          然后看一下生成的 app.js 文件:

          sourcemap

          可以看到在最后生成了 sourcemap 內(nèi)容,在開發(fā)中可以方便的借助于它來進(jìn)行調(diào)試了。

          當(dāng)然,如果你想將生成的 sourcemap 與我們的 js 文件分離開,可以借助于?exorcist?來實(shí)現(xiàn)(exorcist 原意為“驅(qū)魔人”,這里指代的是,將文件中的 sourcemap 部分的內(nèi)容“驅(qū)趕”到另一個(gè)單獨(dú)文件中去,更多用法請參考:exorcist[1]):

          修改我們的命令為:

          browserify?-d?-r?uniq?-r?index.js:myModule?|?npx?exorcist?./app.js.map?>?./app.js?

          執(zhí)行后你就會發(fā)現(xiàn),你的 app.js 和 它對應(yīng)的 sourcemap 文件已經(jīng)分離了:

          external sourcemap

          多文件打包

          當(dāng)多個(gè)頁面同時(shí)用到某一個(gè)相同的文件時(shí),我們希望單獨(dú)抽離出這個(gè)文件,再結(jié)合緩存機(jī)制,可以實(shí)現(xiàn)高效的加載。在 browserify 中我們可以通過?--external(簡寫 -x) 和?--require(簡寫 -r) 來實(shí)現(xiàn)。

          比如我們此時(shí)有如下文件:

          utils.js(公用的工具庫):

          function?add(a,?b)?{
          ??return?a?+?b;
          }

          function?minus(a,?b)?{
          ??return?a?-?b;
          }

          function?upper(str)?{
          ??return?String(str).toLocaleUpperCase()
          }

          module.exports?=?{
          ??add,
          ??minus,
          ??upper
          }

          sum.js:

          const?{?add?}?=?require("./utils")

          console.info(add(1,2))

          upper.js:

          const?{?upper?}?=?require("./utils")

          console.info(upper("hello"))

          我們想將 utils.js 單獨(dú)打包成一個(gè)文件,然后 sum.js 和 upper.js 的打包文件中不用包含這個(gè) utils.js 的代碼,而且直接 require 引入,我們需要如下三個(gè)命令:

          //?單獨(dú)打包?utils.js?文件為?common.js?文件
          browserify?-r?utils.js?-o?./lib/common.js

          //?打包?sum.js,并且指定其使用的?utils.js?為外部模塊(即不需要將這個(gè)?utils.js?打包進(jìn)來)
          browserify?-x?utils.js?sum.js?-o?./lib/sum.js

          //?打包?upper.js,并且指定其使用的?utils.js?為外部模塊(即不需要將這個(gè)?utils.js?打包進(jìn)來)
          browserify?-x?utils.js?upper.js?-o?./lib/upper.js

          依次執(zhí)行后會在當(dāng)目錄下生成 lib 文件夾,里面有三個(gè)打包后的文件:

          lib/common.js:

          require=(function(){function?r(e,n,t){function?o(i,f){if(!n[i]){if(!e[i]){var?c="function"==typeof?require&&require;if(!f&&c)return?c(i,!0);if(u)return?u(i,!0);var?a=new?Error("Cannot?find?module?'"+i+"'");throw?a.code="MODULE_NOT_FOUND",a}var?p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var?n=e[i][1][r];return?o(n||r)},p,p.exports,r,e,n,t)}return?n[i].exports}for(var?u="function"==typeof?require&&require,i=0;ireturn?o}return?r})()({"/src/03-multiple/utils.js":[function(require,module,exports){
          function?add(a,?b)?{
          ??return?a?+?b;
          }

          function?minus(a,?b)?{
          ??return?a?-?b;
          }

          function?upper(str)?{
          ??return?String(str).toLocaleUpperCase()
          }

          module.exports?=?{
          ??add,
          ??minus,
          ??upper
          }
          },{}]},{},[]);

          lib/sum.js

          (function(){function?r(e,n,t){function?o(i,f){if(!n[i]){if(!e[i]){var?c="function"==typeof?require&&require;if(!f&&c)return?c(i,!0);if(u)return?u(i,!0);var?a=new?Error("Cannot?find?module?'"+i+"'");throw?a.code="MODULE_NOT_FOUND",a}var?p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var?n=e[i][1][r];return?o(n||r)},p,p.exports,r,e,n,t)}return?n[i].exports}for(var?u="function"==typeof?require&&require,i=0;ireturn?o}return?r})()({1:[function(require,module,exports){
          const?{?add?}?=?require("./utils")

          console.info(add(1,2))
          },{"./utils":"/src/03-multiple/utils.js"}]},{},[1]);

          lib/upper.js

          (function(){function?r(e,n,t){function?o(i,f){if(!n[i]){if(!e[i]){var?c="function"==typeof?require&&require;if(!f&&c)return?c(i,!0);if(u)return?u(i,!0);var?a=new?Error("Cannot?find?module?'"+i+"'");throw?a.code="MODULE_NOT_FOUND",a}var?p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var?n=e[i][1][r];return?o(n||r)},p,p.exports,r,e,n,t)}return?n[i].exports}for(var?u="function"==typeof?require&&require,i=0;ireturn?o}return?r})()({1:[function(require,module,exports){
          const?{?upper?}?=?require("./utils")

          console.info(upper("hello"))
          },{"./utils":"/src/03-multiple/utils.js"}]},{},[1]);

          可以看到,common.js 中包含著公有的方法,sum.js 和 upper.js 中只包含著自己的業(yè)務(wù)邏輯,而外部模塊的使用是通過 require 來引入的。我們來驗(yàn)證一下是否可以運(yùn)行:

          新建一個(gè) sum.html 文件,引入:

          <script?src="./lib/common.js">script>
          <script?src="./lib/sum.js">script>

          運(yùn)行結(jié)果如下圖,可以看到正確的輸出了結(jié)果。

          multiple bundles

          封裝 npm scripts

          在開發(fā)過程中,我們通常會將一些常用的構(gòu)建命令封裝成 npm 腳本去執(zhí)行,這樣可以減小我們輸錯(cuò)腳本內(nèi)容的幾率,我們在 package.json 文件中增加 scripts

          {
          ??"scripts":?{
          ????"build":?"browserify?index.js?>?app.js"
          ??}
          }

          接著我們執(zhí)行?npm run build?就可以完成同樣的任務(wù)了,這也是最佳實(shí)踐的一種。

          進(jìn)階用法

          使用 ES Module

          如果你使用的是 import 或者 export 這樣的 ES6 的模塊化語言來引入其他模塊的話,browserify 也提供了插件支持這樣的語法。我們需要安裝如下依賴:

          npm?install?--save-dev?@babel/core?@babel/preset-env?babelify

          然后添加 babel.config.json 配置文件來配置 babel:

          {
          ??"presets":?["@babel/preset-env"]
          }

          假設(shè)此時(shí)我們的 index.js 文件如下:

          import?uniq?from?"uniq";

          console.info(uniq([1,2,3,1,2,3]))

          那么要像讓 browserify 正確的打包,需要如下命令:

          browserify?index.js?>?app.es.js?-t?babelify

          代碼壓縮

          假設(shè)我們的 index.js 中出現(xiàn)了沒有使用的變量或者方法,這些代碼永遠(yuǎn)不會被執(zhí)行,那么打包進(jìn)最終的生成文件無疑是一種浪費(fèi)。browserify 也提供了這樣的插件來優(yōu)化我們的生成代碼,比如:刪除未使用的變量,刪除無效的代碼,壓縮代碼等。

          我們需要安裝這個(gè)插件

          npm?install?--save-dev?tinyify

          假設(shè)我們的 index.js 是這樣的:

          const?name?=?'Hello';
          const?version?=?1.1;

          function?add(a,?b)?{
          ??return?a?+?b;
          }

          function?upper(str)?{
          ??return?str.toUpperCase()
          }

          console.info(add(name,?version))

          首先我們看一下不使用插件的打包輸出:

          browserify?index.js?>?app.big.js

          生成的 app.big.js 文件內(nèi)容:

          (function(){function?r(e,n,t){function?o(i,f){if(!n[i]){if(!e[i]){var?c="function"==typeof?require&&require;if(!f&&c)return?c(i,!0);if(u)return?u(i,!0);var?a=new?Error("Cannot?find?module?'"+i+"'");throw?a.code="MODULE_NOT_FOUND",a}var?p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var?n=e[i][1][r];return?o(n||r)},p,p.exports,r,e,n,t)}return?n[i].exports}for(var?u="function"==typeof?require&&require,i=0;ireturn?o}return?r})()({1:[function(require,module,exports){
          const?name?=?'Hello';
          const?version?=?1.1;

          function?add(a,?b)?{
          ??return?a?+?b;
          }

          function?upper(str)?{
          ??return?str.toUpperCase()
          }

          console.info(add(name,?version))


          },{}]},{},[1]);

          我們可以看到,index.js 中的代碼原樣的被包裹在匿名函數(shù)中。并且我們的源代碼中沒有使用其他模塊,但是打包后的文件還是模塊引入之類的代碼打包進(jìn)來了。我們使用 tinyify 插件再看看:

          browserify?index.js?>?app.big.js?-p?tinyfiy

          生成的 app.small.js 文件內(nèi)容如下:

          console.info("Hello1.1");

          對,你沒有看錯(cuò),就是這么一行代碼!簡單粗暴!其實(shí)讀者回過頭來看一下 index.js 的代碼,無非也就是這么一行輸出代碼而已。所以,借助于 tinyify 插件,我們可以有效的減少打包文件的體積,提升程序加載速度與運(yùn)行效率。

          監(jiān)聽文件修改

          在開發(fā)過程中,我們不希望每次修改文件都要去手動的執(zhí)行構(gòu)建腳本,所以需要這樣一個(gè)工具來監(jiān)聽文件的修改,一有變動立即執(zhí)行構(gòu)建邏輯。我們可以使用 watchify 來實(shí)現(xiàn)這樣的效果。首先安裝這個(gè)模塊:

          npm?install?watchify

          接著只要運(yùn)行如下的命令即可:

          watchify?index.js?-o?app.js

          當(dāng)我們的 index.js 文件修改時(shí),app.js 就會被重新生成,刷新瀏覽器后就可以看到最新的結(jié)果了。

          我們可以將上述三個(gè)腳本封裝成 npm scripts 來使用:

          {
          ??"scripts":?{
          ????"dev":?"watchify?index.js?-o?app.js",
          ????"build":?"browserify?index.js?-o?app.js?-p?tinyify",
          ????"build:es":?"browserify?index.js?>?app.es.js?-t?babelify?-p?tinify",
          ??}
          }

          好了,關(guān)于 browserify 的使用就介紹到這里,如果想了解更多,可以去翻閱它的官網(wǎng)[2]掌握更多用法。

          參考資料

          [1]?

          exorcist:?https://github.com/thlorenz/exorcist

          [2]?

          官網(wǎng):?http://browserify.org/


          -?EOF -?


          更多優(yōu)秀開源項(xiàng)目(點(diǎn)擊下方圖片可跳轉(zhuǎn))





          如果覺得本文介紹的開源項(xiàng)目不錯(cuò),歡迎轉(zhuǎn)發(fā)推薦給更多人。



          分享、點(diǎn)贊和在看

          支持我們分享更多優(yōu)秀開源項(xiàng)目,謝謝!

          瀏覽 61
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色天天干| 国产21区| AA黄色片| 丁香花高清在线完整版 | 无码人妻 一区二区三区 |