使用 gulp 搭建前端環境之 CommonJs & ES6 模塊化(中級篇)

  1. browserify 簡介javascript

  2. 編寫 CommonJS 模塊示例html

  3. 編寫 ES6 Module 模塊示例前端

  4. 總結 CommonJs 和 ES6 Modulejava

  5. 參考文檔node

概要:本篇文章的主要任務是使用 ES6 語法來編寫 CommonJs 模塊化和使用 ES6 提供的 Module 來實現模塊化,跟着下面的步驟一步一步來:github

  • 編寫 CommonJS 模塊示例npm

  • 編寫 ES6 Module 模塊示例json

1. browserify 簡介示例

1.1 browserify 是什麼

"Browserify lets you require('modules') in the browser by bundling up all of your dependencies." - Browserify.org

上面的描述是摘自 browserify 官網;用通俗的話講就是:browserify 是一個瀏覽器端代碼模塊化工具,能夠處理模塊之間的依賴關係,讓服務器端的 CommonJS 格式的模塊能夠運行在瀏覽器端

1.2 browserify入門

browserify的原理:

處理代碼依賴,將模塊打包到一塊兒


browserify


打包爲單個文件存在的問題:

  • 暫時用不到的代碼也會被打包,體積大,首次加載速度慢

  • 只要一個模塊更新,整個文件緩存失效

注:暫時用不到的代碼指不一樣的頁面有不一樣的 JS 文件,不須要在當前頁面引用其餘頁面的代碼即爲暫時用不到的代碼

Browserify的解決方案:
entry point,入口點技術;每一個入口點打包一個文件,兩個入口點的相同依賴模塊單獨打包爲common.js

1.3 安裝配置
  • 安裝 browserify

npm install --global browserify
  • 引入 browserify

import  browserify from 'browserify'
  • 基本配置

glup.taks('browserify', function() {
  browserify({
     //先處理依賴,入口文件
     entries: ['./foo.js','./main.js'],
     //進行轉化
     transform: []
  })
   .bundle() // 多個文件打包成一個文件
   .pipe(source()) // browserify的輸出不能直接用作gulp輸入,因此須要source進行處理 
   .pipe(gulp.dest('./'));  
})
1.4 安裝一些依賴插件
npm install --save-dev vinyl-source-stream vinyl-buffer gulp-sourcemaps
  • vinyl-source-stream: browserify的輸出不能直接用着gulp的輸入,vinly-source-stream 主要是作一個轉化

  • vinyl-buffer: 用於將vinyl流轉化爲buffered vinyl文件(gulp-sourcemaps及大部分Gulp插件都須要這種格式)

  • gulp-sourcemaps: Source map就是一個信息文件,裏面儲存着位置信息。也就是說,轉換後的代碼的每個位置,所對應的轉換前的位置,便於調試

  • Watchify: 加速 browserify 編譯

2. 編寫 CommonJS 模塊示例

2.1 目錄結構
/
|-- dist/
   |-----bundle.js
|-- src/
   |-----foo.js
   |-----main.js
|--gulpfile.babel.js
|--package.json
2.2 新建兩個模塊文件 foo.js, main.js
$ touch foo.js main.js
2.3 讓我使用 CommonJs 規範來寫一些代碼

CommonJS 規範是爲了解決 JavaScript 的做用域問題而定義的模塊形式,能夠使每一個模塊在它自身的命名空間中執行。該規範的主要內容是,模塊必須經過 module.exports 導出對外的變量或接口,經過 require() 來導入其餘模塊的輸出到當前模塊做用域中。

// foo.js
// 定義foo.js模塊,經過 module.exports 導出對外的變量或接口
let variable = 8;
let sum = (a, b = 6) => (a + b);
let square = (b) => {
    return b * b;
};
module.exports.variable = variable;
module.exports.sum = sum;
module.exports.square = square;
// mian.js
// 經過 require() 來導入 foo.js 模塊
var bar = require('./foo')
console.log(bar);  // Object
console.log(bar.variable); // 8
console.log(bar.sum(1)); // 7
console.log(bar.square(5)); // 25

上面咱們使用 ES6 的語法寫了兩個模塊,分別是 foo.jsmain.js; 在 foo.js 中經過 module.exports 導出對外的變量或接口;在 main.js 中經過 require() 來導入 foo.js 模塊,那咱們就能夠在 mian.js 模塊中使用 foo.js 中的變量和接口了。這就是一個最基本的 CommonJs 示例了

2.4 配置 browserify

經過第一小節的學習,咱們知道要在瀏覽器中運行 CommonJs 風格的模塊代碼,就須要藉助 browserify 來做爲轉換工具,下面咱們在 gulp.babel.js 中來配置 browserify

// set browserify task
gulp.task('browserify',()=> {
    browserify({
        entries: ['src/js/main.js','src/js/foo.js'],
        debug: true, // 告知Browserify在運行同時生成內聯sourcemap用於調試
    })
        .transform("babelify", {presets: ["es2015"]})
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(buffer()) // 緩存文件內容
        .pipe(sourcemaps.init({loadMaps: true})) // 從 browserify 文件載入 map
        .pipe(sourcemaps.write('.')) // 寫入 .map 文件
        .pipe(gulp.dest('dist/js'))
        .pipe(notify({ message: 'browserify task complete' }));
})
2.5 運行
gulp-browserify

gulp-browserify

2.6 打開瀏覽器,查看運行結果(見上面main.js文件的註釋)

3. 編寫 ES6 Module 模塊示例

上面的代碼主要是 CommonJs 模塊化的寫法,咱們再來看看最近火熱的 ES6 提供的 Module;讓咱們使用 ES6 Module 來改寫上面的代碼:

// foo.js
// 定義foo.js模塊,經過 exports 導出對外的變量或接口
let variable = 8;
let sum = (a, b = 6) => (a + b);
let square = (b) => {
    return b * b;
};
export { variable, sum, square };
// main.js
// 測試一:
// 經過 import 來導入 foo.js 模塊
import {variable, sum, square} from './foo';
console.log(variable); // 8
console.log(sum(1)); // 7
console.log(square(5)); // 25

// 測試二:
// 直接引用整個 foo 模塊
import bar from './foo';
console.log(bar); // 輸出值是undefined,後面作解釋

// 測試三:
// 經過 ES6 的語法加載整個 foo模塊
import * as bar from './foo'
console.log(bar); // Object

4. 總結 CommonJs 和 ES6 Module

4.1 CommonJs
  • 根據 CommonJS 規範,一個單獨的文件就是一個模塊。每個模塊都是一個單獨的做用域,也就是說,在一個文件定義的變量(包括函數和類),都是私有的,對其餘文件是不可見的

  • 經過 module.exports 對象,定義對外接口,其餘文件加載該模塊,實際上就是讀取 module.exports 變量

  • 經過 require 命令加載模塊文件,而後返回該模塊的exports對象

4.2 ES6 Module
  • 經過 export 命令用於規定模塊的對外接口

  • 經過 import 命令用於加載其餘模塊提供的功能

4.3 ES6 Module 與 CommonJs 的區別
  • 在ES6中使用 import 取代 require

  • 在ES6中使用 export 取代 module.exports

  • ES6 在編譯時就能肯定模塊的依賴關係,以及輸入和輸出的變量,而 CommonJs 只能在運行時肯定模塊的依賴關係以及輸入和輸出的變量。

    • 運行時加載: CommonJS 模塊就是對象;即在輸入時是先加載整個模塊,生成一個對象,而後再從這個對象上面讀取方法,這種加載稱爲「運行時加載」

    • 編譯時加載: ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,輸入時採用靜態命令的形式。即在輸入時能夠指定加載某個輸出值,而不是加載整個模塊,這種加載稱爲「編譯時加載」

注:上面提到 ES6 加載模塊時是採用指定加載某個輸出值的形式,若是你要想加載整個模塊,你能夠這麼作:import * as customName from './moduleFileName';

5. 參考文檔

相關文章
相關標籤/搜索