如今流行 mvvm
三大框架,各類cli
工具也給咱們提供了不少方便。我在工做中使用的是vue 技術棧。vue-cli
讓我不能更爽了。分分鐘拉起架子,開始各類業務代碼。javascript
可是,工做中我還遇到另外一種狀況,就是我須要寫一些 SDK
文件,有對內的也有對外的。每次寫這個都讓我蛋疼的不要不要的,若是使用 cli
,須要依賴,文件太大不合適。若是手工去寫,好多es6
的語法用不上,還得本身處理 polyfill
。 索性根據須要本身搭建一套腳手架。css
開始以前,咱們先分析下須要哪些功能。SDK
通常都是提供一些Api方法,其中絕大多數可能都是JS。因此咱們可能須要如下的一些能力。vue
import
。webpack
和 gulp
都是目前比較流行的構建工具。此次咱們使用 gulp 來構建。java
首先新建一個空的文件sdk-cli
。而後執行如下命令,初始化一個package.json 文件。node
npm init -y
複製代碼
下一步,咱們全局和本地安裝gulp。webpack
npm install -g gulp
npm install gulp --save-dev
複製代碼
咱們在跟目錄下新建一個 ``gulpfile.js。git
// gulpfile.js
const gulp = require('gulp');
複製代碼
同時,咱們在根目錄下建立一個app.js
文件。es6
// app.js 測試代碼
let SDK = {
show: () =>{
console.log('this is function')
},
init(options){
let _opt = {
name:'zhangsan',
age: 23
}
options = Object.assign(_opt,options);
console.log(options);
}
}
window.SDK = SDK;
複製代碼
下一步,咱們開始編譯上面的app.js
文件,最後輸出。github
編譯ES6,咱們就須要用到 gulp-babel
這個插件了。web
npm install gulp-babel --save-dev
複製代碼
同時,咱們須要建立一個 .babelrc
的文件,這個文件是定義了一些 babel
的規則。
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage", //根據代碼的須要加載polyfill
"corejs": 3 // 依賴corejs-3
}
]
]
}
複製代碼
主要是把es6的語法轉換爲es5的語法。
下面咱們往 gulpfile.js
中添加一些代碼。
const gulp = require('gulp');
const babel = require('gulp-babel');
function js(){
return gulp.src('./app.js') // 輸入 app.js
.pipe(babel()) // babel 轉換代碼
.pipe(gulp.dest('./dist/')) // 輸出到dist文件夾下,會自動建立文件夾
}
exports.js = js; // 輸出task任務爲js
複製代碼
而後咱們執行構建代碼
gulp js
複製代碼
而後咱們會看到報錯
$ gulp js
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module '@babel/core'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:690:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (D:\hlmy\learning\sdk-clis\node_modules\gulp-babel\index.js:7:15)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
複製代碼
這是由於雖然咱們安裝了 gulp-babel
,他只是一個工具庫,他還須要用到 @babel/core
這個核心庫。一樣道理,也須要安裝@babel/preset-env
npm install @babel/core @babel/preset-env -D
複製代碼
安裝完以後,咱們在試着跑下命令
gulp js
複製代碼
咱們會看到此次成功了,在 dist
文件夾下輸出了一個 app.js
文件。
他是長這樣的,
"use strict";
require("core-js/modules/es.object.assign");
// app.js 測試代碼
var SDK = {
show: function show() {
console.log('this is function');
},
init: function init(options) {
var _opt = {
name: 'zhangsan',
age: 23
};
options = Object.assign(_opt, options);
console.log(options);
}
};
window.SDK = SDK;
複製代碼
跟咱們的源文件比一下,會發現他把一些es6的語法,好比 箭頭函數
, 對象寫法
轉換成了 es5
的語法。
babel
轉換是分爲兩部分,一個是轉換語法,一個是轉換 api
。默認狀況下直接轉換語法,api部分是經過polyfill
來實現的。
例如: Object.assign
就是經過引入require("core-js/modules/es.object.assign");
來解決。
這是由於,babel 默認是轉換成commonjs
格式的,這是啥意思呢,就是說他最終轉換成能在node 服務中使用。
若是咱們想要在瀏覽器中再次能使用,就得再次處理。好比下面這個插件。
npm install browserify vinyl-source-stream -D
複製代碼
咱們在改一下 gulpfile.js
文件
const gulp = require('gulp');
const babel = require('gulp-babel');
const browserify = require('browserify');
const source = require('vinyl-source-stream');
function js(){
return gulp.src('./app.js') // 輸入 app.js
.pipe(babel()) // babel 轉換代碼
.pipe(gulp.dest('./dist/')) // 輸出到dist文件夾下,會自動建立文件夾
}
function browser(){
var b = browserify({
entries: "dist/app.js"
});
return b.bundle()
// 將常規流轉換爲包含 Stream 的 vinyl 對象
.pipe(source("bundle.js"))
.pipe(gulp.dest("dist/"));
}
exports.js = js; // 輸出task任務爲js
exports.browser = browser;
複製代碼
此次咱們引入了兩個插件browserify
和 vinyl-source-stream
。
browserify
就是把 commonjs
格式轉換成 瀏覽器可用的文件。功能很強大,咱們這裏主要使用的是他的基本功能。
vinyl-source-stream
這個插件是把常規的數據流轉換成包含 Stream
的 vinyl
對象。
咱們都知道 gulp
是流處理,可是它的流和 咱們一般所說的 node
的流不是一個東西。gulp
的流是基於 vinyl
, 這是一個虛擬對象格式。
咱們去 vinyl 的官網看下,他的用法是這樣的。
var Vinyl = require('vinyl');
var jsFile = new Vinyl({
cwd: '/',
base: '/test/',
path: '/test/file.js',
contents: new Buffer('var x = 123')
});
複製代碼
vinyl格式除了內容外,還包含一些路徑的信息。它的contents總共有三種格式,Stream
Buffer
和 null
。
而gulp 默認使用的是 包含 Buffer
的 vinyl
對象。
那爲何gulp 不使用普通的 node 的Stream流呢,而要本身弄一個 vinyl 虛擬格式呢?咱們看一下以下代碼:
function css(){
gulp.src('./css/**/*.css')
.pipe(gulp.dest('./dist'))
}
exports.css = css;
複製代碼
這段代碼的意思是,把css目錄下的全部css文件,複製到dist目錄下。
請注意這個包含多級目錄,咱們知道gulp會自動建立沒有的目錄和文件名。而node 的stream 流呢,他只傳輸Stream Buffer這些,不關心路徑的問題。因此就須要使用 vinyl
格式。
其實 vinyl
虛擬格式是一個對普通流的包裝。
言歸正傳,咱們接着寫構建。若是你如今去運行構建命令 gulp browser
,是會報錯的。爲何呢,由於咱們還須要安裝core-js
。gulp 的 polyfill
都是經過這個庫包含的,因此咱們須要安裝。
npm install core-js -D
複製代碼
而後咱們在運行一下
gulp browser
複製代碼
咱們打開 dist
看一下,下面有兩個文件app.js
和 bundle.js
。
bundle.js
使咱們最終所須要的文件。
主要轉換工做,已經作完。剩下咱們還須要一些掃尾工做,好比 壓縮
。
上面是兩步操做,因此咱們也須要合併,刪除一些中間文件。
最終以下:
// gulpfile.js
const gulp = require('gulp');
// 編譯es6
const babel = require('gulp-babel');
// 編譯commonjs
const browserify = require('browserify');
// 轉換爲stream的vinyl對象
const source = require('vinyl-source-stream');
// 轉換爲buffer的vinyl對象
const buffer = require('vinyl-buffer');
// 壓縮
const uglify = require("gulp-uglify");
// 清除文件
const clean = require('gulp-clean');
function js(){
return gulp.src('./app.js') // 輸入 app.js
.pipe(babel()) // babel 轉換代碼
.pipe(gulp.dest('./dist/')) // 輸出到dist文件夾下,會自動建立文件夾
}
function browser(){
var b = browserify({
entries: "dist/app.js"
});
return b.bundle()
// 將常規流轉換爲包含 Stream 的 vinyl 對象
.pipe(source("bundle.js"))
// 將 vinyl 對象內容中的 Stream 轉換爲 Buffer
.pipe(buffer())
// 壓縮
.pipe(uglify())
.pipe(gulp.dest("dist/"));
}
// 刪除中間文件
async function del(){
await gulp.src('./dist/app.js')
.pipe(clean())
}
exports.js = js; // 輸出task任務爲js
exports.browser = browser;
// 順序執行task
exports.es = gulp.series( js,browser,del)
複製代碼
差很少到如今爲止,一個簡單的構建就出來了。可用知足使用了。
另外,gulp
,babel
browserify
都是很靈活的。因此以上的用法只是其中的一個,你們若是有興趣也能夠嘗試用其餘的一些插件來完成。總體思路是這樣。
若是你們對 構建工具開發SDK,有什麼好的方法或者新的。能夠留言一塊兒探討。
全部的代碼在 github上,有須要能夠本身查看。
參考連接: