javascript中的模塊化

javascript中的模塊化

ES6之前,js沒有出現模塊化系統。

  • JS主要在前端的瀏覽器中使用,js文件下載緩存到客戶端,在瀏覽器中執行。比如簡單的表單本地驗證,漂浮一個廣告。服務器端使用ASP、JSP等動態網頁技術,將動態生成數據嵌入一個HTML模板,裏面夾雜着JS後使用 <script> 標 籤,返回瀏覽器端。這時候的JS只是一些簡單函數和語句的組合。
  • 2005年之後,隨着Google大量使用了AJAX技術之後,可以異步請求服務器端數據,帶來了前端交互的巨大變化。 前端功能需求越來越多,代碼也越來也多。隨着js文件的增多,災難性的後果產生了。由於習慣了隨便寫,js腳本 中各種全局變量污染,函數名衝突,無法表達腳本之間的依賴關係,因爲都是用腳本文件先後加載來實現的。亟待 模塊化的出現。
  • 2008年V8引擎發佈,2009年誕生了Nodejs,支持服務端JS編程,但沒有模塊化是不可以的。
  • 之後產生了commonjs規範。commonjs規範,使用全局require函數導入模塊,使用exports導出變量。爲了將這種模塊化規範向前端開發遷移,又演化出其它的規範。例如AMD。
  • AMD(Asynchronous Module Definition)異步模塊定義,使用異步方式加載模塊,模塊的加載不影響它後面語 句的執行。所有依賴這個模塊的語句,都需要定義在一個回調函數,回調函數中使用模塊的變量和函數,等模塊加 載完成之後,這個回調函數纔會執行,就可以安全的使用模塊的資源了。其實現就是AMD/RequireJs。AMD雖然是 異步,但是會預先加載和執行。
  • CMD(Common Module Definition),使用seajs,作者是淘寶前端玉伯,兼容幷包解決了RequireJs的問題。 CMD推崇as lazy as possible,儘可能的懶加載。
  • 由於社區的模塊化呼聲很高,ES6開始提供支持模塊的語法,但是瀏覽器目前支持還不夠。

ES6模塊化

  • import語句,導入另一個模塊導出的綁定。
  • export語句,從模塊中導出函數、對象、值的,供其他模塊import導入用。

導出

  • 建立一個模塊目錄src,然後在這個目錄下新建一個moda.js,內容如下:
//缺省導出
export default class A{
    constructor(x){
        this.x = x;
    }
    show(){
        console.log(this.x)
    }
}

//導出函數
export function foo(){
    console.log('foo function');
}

//導出常量
export const CONSTA = 'aaa';
  • 在src目錄中建立text.js導入moda.js中的內容,並使用,如下:
import {A,foo} from "./moda"
import * as mod_a from "./moda"

VS Code可以很好的語法支持了,但是運行環境,包括V8引擎,都不能很好的支持模塊化語法。

轉譯工具

轉譯就是從一種語言代碼轉換到另一個語言代碼,當然也可以從高版本轉譯到低版本的支持語句。
由於JS存在不同版本,不同瀏覽器兼容的問題。可以使用transpiler轉譯工具解決。

babel

預設

  1. 有如下一些預設presets,我們先看看有哪些,一會兒再進行預設的安裝和配置
    • presets:
      1. babel-preset-env當前環境支持的代碼,新target
    • ES2015轉碼規則
      1. npm install --save-dev babel-preset-es2015
    • react轉碼規則
      1. npm install --save-dev babel-preset-react
    • ES7不同階段語法提案的轉碼規則(共4個階段),選裝一個
      1. npm install --save-dev babel-preset-stage-0
      2. npm install --save-dev babel-preset-stage-1
      3. npm install --save-dev babel-preset-stage-2
      4. npm install --save-dev babel-preset-stage-3

離線轉譯安裝配置

1.初始化npm

  • 打開cmd命令窗口,進入項目根目錄。輸入npm init初始化項目根目錄
PS D:\MyPythonUse\WebJS> npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (webjs) test
version: (1.0.0)
description: babel
entry point: (test.js)
test command:
git repository:
keywords:
author: xdd
license: (ISC)
About to write to D:\MyPythonUse\WebJS\package.json:

{
  "name": "test",
  "version": "1.0.0",
  "description": "babel",
  "main": "test.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "xdd",
  "license": "ISC"
}


Is this OK? (yes) yes
PS D:\MyPythonUse\WebJS>
  • 在項目根目錄下會生成package.json文件,內容就是上面花括號的內容。

2.設置鏡像

  • .npmrc文件。修改npm安裝軟件時默認連接倉庫爲淘寶的npm倉庫。
    1. 可以放到npm的目錄下npmrc文件中
    2. 可以放到用戶家目錄中
    3. 可以放到項目根目錄中
  • 本次放到項目根目錄黃總,內容如下:
    1. 在項目更目錄中新建一個文件名爲.npmrc的文件。寫入registry=https://registry.npm.taobao.org
      • $ echo "registry=https://registry.npm.taobao.org" > .npmrc

3.安裝

  • 項目根目錄下執行npm install babel-core babel-cli --save-dev
    1. –save–dev說明:當你爲你的模塊安裝一個依賴模塊時,正常情況下你得先安裝他們(在模塊根目錄下npm install module-name),然 後連同版本號手動將他們添加到模塊配置文件package.json中的依賴裏(dependencies)。開發用。–save和–save-dev可以省掉你手動修改package.json文件的步驟。
    2. spm install module-name --save 自動把模塊和版本號添加到dependencies部分
    3. spm install module-name --save-dev 自動把模塊和版本號添加到devdependencies部分
  • 安裝完後,在項目根目錄下出現node_modules目錄 ,裏面有babel相關模塊及依賴的模塊。
    在這裏插入圖片描述

4.修改package.json

  • 修改package.json文件中scripts的部分,添加"build": "babel src -d lib"
    1. "build": "babel src -d lib"從src目錄中轉譯後的文件輸出到lib目錄
    2. 修改"license": "ISC""license": "MIT"

mode_003

5.準備目錄

  • 項目根目錄下建立src和lib目錄。
    1. src是源碼文件目錄。
    2. lib是目標目錄。

6.配置babel和安裝依賴

  • 在目錄根目錄下創建.babelrc文件,Json格式。
{
    "presets":["env"]
}
  • env可以根據當前環境自動選擇。
  • 安裝依賴npm install babel-preset-env --save-dev
    mode_004

7.準備js文件

  1. 在src中的mod.js

    // 缺省導出
    export default class A{
        constructor(x){
            this.x = x;
        }
    
        show(){
            console.log(this.x);
        }
    }
    
    export function foo(){
        console.log('foo function');
    }
    
  2. 在src目錄下的index.js

    import A,{foo} from './mod'
    
    var a = new A(100);
    a.show();
    
    foo();
    
    • index.js這段代碼在vs Code的環境下執行出錯。估計很難有能夠正常運行的環境。所以,要轉義爲ES5的代碼。

8.轉義js文件

  1. 在項目根目錄下執行命令npm run build

    $ npm run build
    
    > [email protected] build D:\MyPythonUse\WebJS
    > babel src -d lib
    
    src\index.js -> lib\index.js
    src\mod.js -> lib\mod.js
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $
    
    • 可以看到兩個文件被轉義,運行轉義文件node lib/index.js
    $ node lib/index.js
    100
    foo function
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    
    • 使用babel等轉譯器轉譯JS非常流行。開發者可以在高版本中使用新的語法特性,提高開發效率,把兼容性問題交給轉譯器處理。

9.可能出現的錯誤

  • .babelrc文件錯誤。重新刪除.babelrc文件後再重新建立一個該文件。
  1. 錯誤信息

    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ npm run build
    
    > [email protected] build D:\MyPythonUse\WebJS
    > babel src -d lib
    
    SyntaxError: D:\MyPythonUse\WebJS\.babelrc: Error while parsing JSON - Unexpected '�' at line 1 column 2 of the JSON5 data. Still to read: "��{\u0000\r\u0000\n\u0000\t\u0000\"\u0000p\u0000r\u0000e\u0000s\u0000"
        at error (D:\MyPythonUse\WebJS\node_modules\json5\lib\json5.js:56:25)
        at word (D:\MyPythonUse\WebJS\node_modules\json5\lib\json5.js:393:13)
        at value (D:\MyPythonUse\WebJS\node_modules\json5\lib\json5.js:493:56)
        at Object.parse (D:\MyPythonUse\WebJS\node_modules\json5\lib\json5.js:508:18)
        at ConfigChainBuilder.addConfig (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\options\build-config-chain.js:150:65)
        at ConfigChainBuilder.findConfigs (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\options\build-config-chain.js:96:16)
        at buildConfigChain (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\options\build-config-chain.js:61:13)
        at OptionManager.init (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\options\option-manager.js:354:58)
        at File.initOptions (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\index.js:212:65)
        at new File (D:\MyPythonUse\WebJS\node_modules\babel-core\lib\transformation\file\index.js:135:24)
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! [email protected] build: `babel src -d lib`
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the [email protected] build script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     C:\Users\gdy\AppData\Roaming\npm-cache\_logs\2019-07-06T13_06_31_034Z-debug.log
    
  2. 解決辦法

    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ rm .babelrc
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ echo "{\"presets\": [\"env\"]}" >.babelrc
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ cat .babelrc
    {"presets": ["env"]}
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ npm run build
    
    > [email protected] build D:\MyPythonUse\WebJS
    > babel src -d lib
    
    src\index.js -> lib\index.js
    src\mod.js -> lib\mod.js
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $
    

導入導出

  • 說明:導出代碼都在src/mod.js中,導入代碼都寫在src/index.js中。

缺省導入導出

  • 只允許一個缺省導出,缺省導出可以是變量、函數、類,但不能使用let、var、const關鍵字作爲默認導出。
  • 缺省導入,不需要在import後使用花括號。
  • 缺省導入的時候,可以自己重新命名,可以不需要和缺省導出時的名稱一致,但最好一致。
  • 可以使用import * as 新名稱 from '模塊'語法來導入所有導出。
  1. src/mod.js中

    //缺省導出 匿名函數
    export default function() {
        console.log('我是缺省導出')
    }
    
  2. src/index.js中

    //缺省導入
    import defaultFunc from './mod'
    defaultFunc();
    
  3. 控制檯執行命令:

    $ npm run build
    
    > [email protected] build D:\MyPythonUse\WebJS
    > babel src -d lib
    
    src\index.js -> lib\index.js
    src\mod.js -> lib\mod.js
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ node lib/index.js
    我是缺省導出
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $
    
  • 第二種示例

    // mod模塊中
    // 缺省導出 命名函數
    export default function xyz(){
        console.log('default export function')
    }
    
    // index模塊中
    //缺省導入
    import defaultFunc from './mod'
    defaultFunc();
    
  • 命名導入和導出

  1. src/mod.js中

    /**
     * 導出舉例
     */
    
    //缺省導出 類
    export default class {
        constructor(x){
            this.x = x;
        }
        show(){
            console.log(this.x);
        }
    }
    
    // 命名導出 函數
    export function foo(){
        console.log('我是函數foo');
    }
    
    // 定義函數
    function bar(){
        console.log("我是函數bar()");
    }
    
    // 變量常量定義
    let x = 100;
    var y = 200;
    const z = 300;
    
    //導出
    export {bar,x,y,z}
    
  2. src/index.js中

    /**
     * 導入舉例
     * as 設置別名
     */
    
    import defaultCls,{foo,bar,x,y,z as CONST_C} from './mod';
    
    foo();
    bar();
    console.log(x); //x只讀,不可修改,x++會出現異常
    console.log(y); //y只讀
    console.log(CONST_C);
    
    let fun =new defaultCls(1000);
    fun.show();
    
  3. cmd命令行中執行

    $ npm run build
    
    > [email protected] build D:\MyPythonUse\WebJS
    > babel src -d lib
    
    src\index.js -> lib\index.js
    src\mod.js -> lib\mod.js
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $ node ./lib/index.js
    我是函數foo
    我是函數bar()
    100
    200
    300
    1000
    
    gdy@gdy MINGW64 /d/MyPythonUse/WebJS
    $
    
  • 在index.js文件中也可以使用下面形式,導入所有導出,但是會定義一個新的名詞空間。使用名詞空間可以避免衝突。

    import * as newmod from './mod';
    
    newmod.foo();
    newmod.bar();
    new newmod.default(2000).show();
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章