本篇文章主要闡述瞭如何使用gulp來構建微信小程序原生開發的工做流。javascript
web開發基本上都是基於webpack或者其餘的構建工具來進行開發,大大節約了開發者的時間。目前的微信小程序開發也有不少開源的框架可供選擇,可是若是使用原生開發模式,雖然能夠完美使用小程序原生的新特性和功能,可是工做流角度上卻十分簡陋。css
19年底的時候公司要開發一個新的小程序,組裏面的大佬同事提議使用gulp來構建下原生開發模式的工做流。一是爲了擺脫簡陋的工做流模式以節約開發時間,二是也是把技術用到刀刃上。在大佬的指導開發下,這個工做便進行了。整體來講這個工做並不難,增益可能也沒有那麼大,可是仍是收穫了不少。java
項目地址:gulp-mpwebpack
咱們把開發目錄設置在src
,輸出目錄設置在dist
,定義開發與輸出路徑。git
微信小程序的page目錄一般包含wxml
,json
,wxss
和js
文件,與原生開發模式不一樣的是咱們使用sass
預處理器來寫樣式,其餘的文件保持原樣不一樣。所以,對於wxml
,json
,js
文件來講,僅僅須要copy就行。由於在項目中已經配置了eslint+prettier
來進行語法檢查和代碼美化,所以不須要在工做流的js代碼進行規範檢查。若是沒有配置,能夠安裝gulp-eslint
執行eslint規範檢查。github
const srcPath = "./src/**";
const distPath = "./dist/";
const wxmlFiles = [`${srcPath}/*.wxml`];
const jsFiles = [`${srcPath}/*.js`, `!${srcPath}/env/*.js`];
const jsonFiles = [`${srcPath}/*.json`];
// copy wxml
const wxml = () => {
return gulp
.src(wxmlFiles, { since: gulp.lastRun(wxml) })
.pipe(gulp.dest(distPath));
};
gulp.task(wxml);
// 其餘copy流相似
...
複製代碼
上面咱們提到使用sass
預處理來編寫樣式,在輸出的時候咱們須要把scss
樣式轉換成wxss
,wxss
就是普通的css
樣式。這裏,咱們使用gulp-sass
插件轉換scss樣式。可是,須要注意的是在scss
文件中,咱們可能會import相關樣式,多是公共樣式也多是varibale和minxin。web
通過測試發現,當import公共樣式,會把這個公共樣式打包進當前頁面。咱們知道小程序的包是有大小限制的,若是在引入公共樣式的時候還打包到當前頁面,無疑是消耗掉了沒必要要的內存。因此,針對公共樣式的import處理爲,不交給sass處理,保留import並把後綴的.scss改爲.wxss。npm
當import的是變量和mixin時,咱們須要保留對其的sass處理,所以新建獨立的目錄存放以便識別。在這一場景下,變量和mixin的文件再也不遞歸處理。json
//存放variable和mixin的sass文件在被引用時直接導入,不引入dist目錄中
const DIRECTIMPORT = ["/scss/", "/font/"];
const sassFiles = [`${srcPath}/*.{scss, wxss}`];
const wxss = () => {
return gulp
.src([...sassFiles, ...DIRECTIMPORT.map(item => `!${srcPath}/${item}/*`)], {
since: gulp.lastRun(wxss)
})
.pipe(plumber({ errorHandler: onError }))
.pipe(
tap(file => {
const filePath = path.dirname(file.path);
//console.log("filepath", filePath);
file.contents = new Buffer(
// 匹配@import
String(file.contents).replace(
/@import\s+['|"](.+)['|"];/g,
($1, $2) => {
console.log("$1", $1);
console.log("$2", $2);
//若是不是變量或者mixin則註釋掉
return DIRECTIMPORT.some(item => {
return $2.indexOf(item) > -1;
})
? $1
: `/** ${$1} **/`;
}
)
);
})
)
.pipe(sass())
.pipe(postcss([autoprefixer(["iOS >= 8", "Android >= 4.1"])]))
.pipe(
replace(/(\/\*\*\s{0,})(@.+)(\s{0,}\*\*\/)/g, ($1, $2, $3) => {
//console.log("$1", $1);
//console.log("$2", $2);
//console.log("$3", $3);
//去掉註釋並修改scss後綴爲wxss
return $3.replace(/\.scss/g, ".wxss");
})
)
.pipe(rename({ extname: ".wxss" }))
.pipe(gulp.dest(distPath));
};
gulp.task(wxss);
複製代碼
安裝gulp-imagemin插件壓縮圖片。以前經過npm安裝在使用的時候這個插件老是報錯,後來發現是沒有正確安裝,瞎倒騰切換到cnpm或者yarn發現能夠安裝成功了。gulp
const imageFiles = [
`${srcPath}/images/*.{png,jpg,gif,ico}`,
`${srcPath}/images/**/*.{png,jpg,gif,ico}`
];
const img = () => {
return gulp
.src(imageFiles, { since: gulp.lastRun(img) })
.pipe(imagemin())
.pipe(gulp.dest(distPath));
};
gulp.task(img);
複製代碼
正常開發過程當中,開發,測試和發佈環境一般會有不一樣的API接口和其餘設置。在每次切換的時候手動去更改內部代碼是一件很麻煩的事情,也容易遺忘,根據不一樣的命令自動加載相應的開發環境設置纔是咱們想要的效果。 在src/env/*
目錄下,配置了三個環境的變量:dev.js
,test.js
,prod.js
。
const envJs = env => {
return () => {
return gulp
.src(`./src/env/${env}.js`)
.pipe(rename("env.js"))
.pipe(gulp.dest(distPath));
};
};
gulp.task(envJs);
複製代碼
在從新編譯的時候咱們都須要清除dist目錄的資源,以避免致使混亂
/* 清除dist目錄 */
gulp.task("clean", done => {
del.sync(["dist/**"]);
done();
});
複製代碼
使用命令新建page目錄和component目錄,只要把模版文件拷貝並重命名便可。
const newfile = done => {
yargs
.example("gulp newfile -p mypage", "建立mypage的page目錄")
.example("gulp newfile -c mycomponent", "建立mycomponent的component目錄")
.example(
"gulp newfile -s srcfile -p mypage",
"以srcfile爲模版建立mypage的page目錄"
)
.option({
s: {
alias: "src",
describe: "模板",
type: "string",
default: "template"
},
p: {
alias: "page",
describe: "page名稱",
type: "string"
},
c: {
alias: "component",
describe: "component名稱",
type: "string"
}
})
.fail(msg => {
done();
console.error("建立失敗");
console.log(msg);
console.log("help");
yargs.parse(["--msg"]);
})
.help("msg");
const args = yargs.argv;
//console.log("args", args);
const source = args.s;
const filePaths = {
p: "pages",
c: "components"
};
let name,
type,
hasParam = false;
for (let key in filePaths) {
if (args[key]) {
hasParam = true;
name = args[key];
type = filePaths[key];
}
}
if (!hasParam) {
done();
yargs.parse(["--msg"]);
}
const defaultPath =
source === "template"
? `src/${source}/${type}/*`
: `src/${type}/${source}/*`;
return gulp.src(defaultPath).pipe(gulp.dest(`src/${type}/${name}/`));
};
gulp.task(newfile);
複製代碼
優化的工做流比較簡單,無非就是複製文件,scss處理,資源處理,自動建立目錄等。以上只是簡單的示例,若是須要的話能夠引入壓縮插件及其餘插件進行優化。