天天看點

javascript中的子產品化

javascript中的子產品化

文章目錄

  • ​​javascript中的子產品化​​
  • ​​ES6子產品化​​
  • ​​導出​​
  • ​​轉譯工具​​
  • ​​babel​​
  • ​​預設​​
  • ​​離線轉譯安裝配置​​
  • ​​1.初始化npm​​
  • ​​2.設定鏡像​​
  • ​​3.安裝​​
  • ​​4.修改package.json​​
  • ​​5.準備目錄​​
  • ​​6.配置babel和安裝依賴​​
  • ​​7.準備js檔案​​
  • ​​8.轉義js檔案​​
  • ​​9.可能出現的錯誤​​
  • ​​導入導出​​
  • ​​預設導入導出​​

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

  • 開發中可以使用較新的ES6文法,通過轉譯器轉換為指定的某些版本代碼。
  • 官網​​https://babeljs.io/​​
  • 參考文檔​​https://babeljs.io/docs/en/6.26.3/index.html​​注意目前版本7.x已經有了較大的變化,請參看6.x文檔
  • 在​

    ​Try it out​

    ​。中可測試代碼
  • javascript中的子產品化

預設

  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相關子產品及依賴的子產品。
  • javascript中的子產品化

4.修改package.json

  • 修改package.json檔案中scripts的部分,添加​

    ​"build": "babel src -d lib"​

    ​。
  1. ​"build": "babel src -d lib"​

    ​從src目錄中轉譯後的檔案輸出到lib目錄
  2. 修改​

    ​"license": "ISC"​

    ​​為​

    ​"license": "MIT"​

5.準備目錄

  • 項目根目錄下建立src和lib目錄。
  1. src是源碼檔案目錄。
  2. lib是目标目錄。

6.配置babel和安裝依賴

  • 在目錄根目錄下建立​

    ​.babelrc​

    ​檔案,Json格式。
{
    "presets":["env"]
}      
  • ​env​

    ​可以根據目前環境自動選擇。
  • 安裝依賴​

    ​npm install babel-preset-env --save-dev​

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');
}      
  1. 在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 ->      
  • 可以看到兩個檔案被轉義,運作轉義檔案​

    ​node lib/index.js​

$ node lib/index.js
100
foo function      
  • 使用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!      
  1. 解決辦法
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 ->      

導入導出

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

預設導入導出

  • 隻允許一個預設導出,預設導出可以是變量、函數、類,但不能使用let、var、const關鍵字作為預設導出。
  • 預設導入,不需要在import後使用花括号。
  • 預設導入的時候,可以自己重新命名,可以不需要和預設導出時的名稱一緻,但最好一緻。
  • 可以使用​

    ​import * as 新名稱 from '子產品'​

    ​文法來導入所有導出。
  1. src/mod.js中
//預設導出 匿名函數
export default function() {
    console.log('我是預設導出')
}      
  1. src/index.js中
//預設導入
import defaultFunc from './mod'
defaultFunc();      
  1. 控制台執行指令:
$ npm run build

> [email protected] build D:\MyPythonUse\WebJS
> babel src -d lib

src\index.js -> lib\index.js
src\mod.js ->      
  • 第二種示例
// 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}      
  1. 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();      
  1. 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()      
  • 在index.js檔案中也可以使用下面形式,導入所有導出,但是會定義一個新的名詞空間。使用名詞空間可以避免沖突。
import * as newmod from './mod';

newmod.foo();
newmod.bar();
new newmod.default(2000).show();