使用gulp構建微信小程序工作流


前言

剛入門微信小程序的時候,一切都基於微信web開發者工具,沒有使用其他框架,也沒有工程化的概念。當時做的項目都比較簡單,單單用微信web開發者工具倒也得心應手。學了些東西后,就按捺不住地想跳出原生工具的條條框框,把近些日子學的東西都拿出來熬一熬。

已有的一個小程序項目使用了github上一個使用webpack、babel、sass開發的小程序腳手架(wxapp-boilerplate),我需要在不變動原有項目代碼的基礎上,使用gulp來重構項目的工作流。

使用體驗:使用vscode配合各種插件在src目錄下開發,使用微信web開發者工具預覽調試,通過cmd打開服務,可以用gulp命令快速創建page、component模板。還是很nice的。

介紹

根據開發中的剛需和痛點,最終做了以下工作,有實現不到位的,歡迎大家提出建議。

sass編譯成wxss,同時處理了@import直接導入導致單文件過大的問題
修改gulpfile.js的aliasWords可為項目js配置alias
支持在src中的wxs使用es6+
使用微信web開發者工具的Npm構建
gulp命令快速創建page、component模板

項目地址:https://github.com/bluehat999/weapp-gulp

文章地址:https://www.cnblogs.com/mthz/p/weapp-gulp.html

要點

實現過程中遇到的問題,也是一些要點:

1.項目中的WXS文件使用了ES6語法,而WXS原生不支持ES6

wxs不支持ES6 語法,其標准基本是參考ES5 標准.
解決方案是使用babel將wxs像js那樣從ES6轉為ES5,在使用babel的時候,有個模塊始終無法加載到,查出問題應該是babel的依賴間版本不一致的問題,就在github上查了gulp-babel的倉庫,參照readme.md的示例重新安裝模塊和使用,就成功解決。

安裝:

  npm install --save-dev gulp-babel @babel/core @babel/preset-env

使用:

  const f_wxs = done => {
      return gulp.src(WXS, { since: gulp.lastRun(f_wxs) })
          .pipe(plumber({ errorHandler: onError }))
          .pipe(babel({
  			presets: ['@babel/preset-env']
          }))
          .pipe(rename({extname:'.wxs'}))
          .pipe(gulp.dest(DIST))
  }
  gulp.task('wxs', f_wxs)
2.sass編譯成wxss,解決@import導致文件體積過大的問題

css不支持import語法,sass在處理@import時會直接把對應文件添加過來,從而導致wxss文件體積過大。

而wxss支持import語法,同時限制了單包代碼不超過2M,所以需要采用方法避免sass編譯時直接導入樣式,而是沿用@import。簡單來說,就是讓sass編譯時不處理import語句。

可以改sass的源碼,讓它跳過import,也可以在交給sass編譯前將文件中的import語句注釋掉,編譯結束后再取消注釋。

但是不處理import語句也會帶來一個問題:文件中使用了引入文件中的變量和mixin時,會由於沒有引入而找不到變量和mixin。我們需要再給不處理import語句加一個判斷條件。

一般項目都會將全局的(需要被引用的)變量和mixin放在單獨的文件里,而且會適當分成多個,以免單個文件過大。將這些文件放在指定的目錄里,將目錄路徑作為判斷條件來過濾掉需要import的變量和mixin的sass文件。

const SRC = './src/**/'
const SASS = [`${SRC}*.{scss,wxss,scss}`]
const DIRECTIMPORT = [`styles`, `font`]

const f_sass = done => {
    return gulp.src([...SASS,...DIRECTIMPORT.map(item => `!${SRC}${item}/**/*`)], 
                    { since: gulp.lastRun(f_sass) ,allowEmpty:true})
        .pipe(plumber({ errorHandler: onError }))
        .pipe(tap((file) => {
            const filePath = path.dirname(file.path);
            file.contents = new Buffer(
                String(file.contents)
                .replace(/@import\s+['|"](.+)['|"];/g, ($1, $2) => {
                    const imPath = path.resolve(filePath + '/' + $2)    
                    return DIRECTIMPORT.some( item => { return imPath.indexOf(item) > -1} ) ? $1 : `/** ${$1} **/`
            })
            )
        }))
        .pipe(sass())
        .pipe(replace(/(\/\*\*\s{0,})(@.+)(\s{0,}\*\*\/)/g, ($1, $2, $3) => $3.replace(/\.scss/g, '.wxss')))
        .pipe(rename({ extname: '.wxss' }))
        .pipe(gulp.dest(DIST))
}
gulp.task('sass', f_sass)
3.微信小程序使用npm

小程序基礎庫2.2.1以上的版本開始支持npm安裝第三方包。官方文檔

仔細讀了文檔,和它的示例代碼,不過還是被坑了一會。

node_modules必須放在小程序根目錄或其子目錄下,npm的package.json也是,否則在微信web開發者工具對dist進行npm構建時會提示找不到npm。

它的npm構建會在代碼同級目錄生成source map文件,方便做逆向調試。

不過npm的命令是需要在dist目錄的上一級使用的,如果直接放在dist里,上一級就用不了,本來理想的方案是放在dist、修改npm尋找node_modules文件的地點,或者放在上一級、修改開發者工具構建時尋找node_modules文件的地點。

但是我實在沒查到如何修改,也許看源碼可以,所以采用了比較麻煩的方案。就是node_modules放在上一級,寫一個gulp task將它整體復制到dist。node_modules畢竟挺大的,復制一份要用去10幾秒,開銷挺大,不過也只有node_modules更新了需要同步一下,總的來說也還好。

4.使用gulp-tap獲取處理的文件名時並計算一個相對路徑

原有項目使用了webpack來管理文件依賴,改用gulp的話,原有的一些依賴路徑就是錯誤的,(比如引用config和utils目錄下的文件時),如果直接修改代碼,會和項目原有的編程習慣沖突,所以決定直接在gulp構建時來把錯誤的路徑改為正確的相對路徑。

5.微信小程序中使用lodash報錯
Uncaught TypeError: Cannot read property 'prototype' of undefined

找到一篇解釋的很好的文章

按照文章中給出的方案,在開發者工具中構建Npm后,可使用gulp lodash自動修改相應文件來修復這個問題。

6.微信小程序不支持async / await 語法

因為小程序支持ES6轉ES5,我就沒有在gulp中使用babel,沒考慮到小程序對ES6以上的特性不支持。

小程序報了上訴錯誤,我首先查了一下regeneratorRuntime is not defined的錯誤,大致得知是異步的錯誤,找到報錯的代碼,發現使用了async await,猜測是微信小程序不支持,需要引入相應的包,然后google到了比較好的答案。

facebook代碼倉庫下載到了相應源碼(只需要runtime.js就可以了),放入utils中,在使用了async的地方引入。不過我又遇到了下面的問題:

源碼中報錯部位在catch中,文件中既沒有引入也沒有定義這個Function,在網上也找不到答案,考慮在catch中,應該是處理報錯之類的,注釋掉也影響不大,我就把它注釋掉了。

更多改進

改進一定會有的,如果覺得還行或者不行,勞煩關注一下我的博客和github。

項目地址:https://github.com/bluehat999/weapp-gulp

文章地址:https://www.cnblogs.com/mthz/p/weapp-gulp.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM