開門見山地說,小程序在日常開發中使用原生框架來開發還是挺不方便的,比如:
這樣一來和日常開發前端頁面的體驗相比來說,簡直就像在刀耕火種。 那么為了解決這些問題,我們能不能將前端開發中常用的 webpack 移植到小程序開發中呢? 當然可以! 0.源碼地址
1.文件結構既然用 webpack 來編譯源代碼,那么很自然的我們的文件結構首先要分為 src/ 和 dist/,用開發者工具打開的應該是 dist/ 目錄。 1.1.src/ 中文件結構大概長這樣:. ├── app │ ├── app.js │ ├── app.json │ └── app.scss ├── assets │ └── vue-logo.png ├── comps │ └── todo │ ├── todo.js │ ├── todo.json │ ├── todo.less │ └── todo.wxml ├── pages │ └── index │ ├── index.js │ ├── index.json │ ├── index.less │ └── index.wxml ├── scripts │ ├── const │ │ ├── README.md │ │ └── index.js │ └── utils │ ├── README.md │ ├── event.js │ ├── format.js │ ├── index.js │ └── log.js ├── styles │ ├── global.styl │ ├── todomvc-app-css.css │ └── todomvc-common-base.css └── templates └── info.wxml
1.2.dist/ 中文件結構大概長這樣:. ├── app.js ├── app.js.map ├── app.json ├── app.wxss ├── assets │ └── vue-logo.png ├── chunks │ ├── runtime.js │ ├── runtime.js.map │ ├── scripts.js │ ├── scripts.js.map │ ├── vendors.js │ └── vendors.js.map ├── comps │ └── todo │ ├── todo.js │ ├── todo.js.map │ ├── todo.json │ ├── todo.wxml │ └── todo.wxss ├── pages │ └── index │ ├── index.js │ ├── index.js.map │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── project.config.json └── templates └── info.wxml
1.3.整個項目文件結構大概長這樣:. ├── README.md ├── dist/ ├── package.json ├── project.config.json ├── src/ ├── webpack.config.babel.js └── yarn.lock
2.webpack 基礎配置2.1.entry/output小程序場景下的配置應該是多入口,主要分為 app、pages、comps 這三類。
在輸出 output 部分有個坑:因為小程序使用的是 global,所以必須添加配置 output.globalObject 為 global。 不然... thirdScriptError VM937:1 sdk uncaught third Error Cannot read property 'webpackJsonp' of undefined TypeError: Cannot read property 'webpackJsonp' of undefined at http://127.0.0.1:40247/appservice/chunks/runtime.js:34:51 at http://127.0.0.1:40247/appservice/chunks/runtime.js:38:2 at require (http://127.0.0.1:40247/appservice/__dev__/WAService.js:19:7859) at http://127.0.0.1:40247/appservice/__dev__/WAService.js:19:7573 at http://127.0.0.1:40247/appservice/app.js:3:1 at require (http://127.0.0.1:40247/appservice/__dev__/WAService.js:19:7859) at http://127.0.0.1:40247/appservice/appservice?t=1527755092895:1020:9 // runtime var a = window.webpackJsonp = window.webpackJsonp || [] 詳情可參閱這個 pr ps 在 mpvue 中似乎是通過修改 target 實現的... http://mpvue.com/build/mpvue-webpack-target/ 2.2.CommonChunk在 webpack 4 中有一個 breaking change,ref="https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366">即使用 SplitChunksPlugin 替換了之前很常用的 CommonsChunkPlugin 主要提取了三部分的公共代碼:
現在又碰到個新的問題:如何引入這些 chunks? 在前端項目中一般我們通過 HtmlWebpackPlugin 插件在 html 文件中添加 <script> 標簽引入,然鵝小程序中并沒有 html 文件... 計將安出? 總不能每次都手動去 dist/app.js 中 require 這些文件吧? 這時候就要介紹另一款插件了~:BannerPlugin。 這個插件本來是用在文件頭部添加 banner 的,但是也支持插入代碼,因此利用這款插件我們就可以將這些公共依賴在 app.js 中統一引入一次即可。 TODO: 現版本的小程序提供了分包加載能力,因此這里還有優化空間 2.3.CopyWebpackPlugin顧名思義,這款插件的用處就是拷貝,利用這款插件我們就可以實現:
在使用時有一個知識點可以減少代碼量:即 context 選項,這樣就不用寫 n 個 src/了... new CopyWebpackPlugin(copyCfgArr, { context: resolve('src'), }), 2.4.預處理器和 CSS 的處理這部分其實都是常規操作和一般 web 開發沒啥區別,配置好對應的 loader 即可。 需要注意的點就是一定要使用 ExtractTextWebpackPlugin 插件來生成 .wxss 文件。 new ExtractTextPlugin('[name].wxss') 3.webpack + vue-loader這部分談談如何利用 vue-loader 實現在小程序中引用單文件組件(.vue)。 先看看 src/ 下的文件結構: . ├── app │ ├── App.vue │ ├── app.js │ └── app.json ├── assets │ └── vue-logo.png ├── comps │ ├── filter │ │ ├── Filter.vue │ │ └── index.js │ └── todo │ ├── Todo.vue │ └── index.js ├── pages │ ├── index │ │ ├── Index.vue │ │ └── index.js │ └── todos │ ├── Todos.vue │ └── index.js ├── scripts │ ├── const │ │ ├── README.md │ │ └── index.js │ └── utils │ ├── README.md │ ├── event.js │ ├── format.js │ ├── index.js │ └── log.js ├── styles │ ├── global.styl │ ├── todomvc-app-css.css │ └── todomvc-common-base.css └── templates └── info.wxml 其實已經和一般的 web 項目很相似了~ 3.1.vue-loader v15?隨著 webpack 升級到了 v4,官方與之配合的 vue-loader 也升級到了 v15。 現在 Vue Loader 15 使用了一個不一樣的策略來推導語言塊使用的 loader。 簡單來說就是咱們之前配置過的各個預處理器規則會被 vue-loader 自動使用。 因此我們只需要簡單地添加一條規則即可讀取 .vue 文件: { test: /\.vue$/, exclude: /node_modules/, loader: 'vue-loader', options: { compiler: { // mock vue-template-compiler compile: () => ({ staticRenderFns: [], }) }, }, }, options.compiler 是啥? 3.2.options.compileroptions.compiler 覆寫用來編譯單文件組件中 <template> 塊的默認編譯器。 在實際使用單文件組件時,我們通過 <template lang="wxml"> 來包裹原本的 .wxml 文件中的內容。 因為最終要編譯成 .wxml 文件才能被開發者工具識別,所以我們還編寫了一條規則通過 file-loader 生成最終的 .wxml 文件: { // 處理 <template lang="wxml">{...}</template> // 生成 .wxml 文件 test: /\.wxml$/, use: { loader: 'file-loader', options: { name: getNameByFilePathAndExt('.wxml'), }, }, }, |