亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

終極蛇皮上帝視角之微信小程序之告別“刀耕火種”

標簽:
JavaScript

开门见山地说,小程序在日常开发中使用原生框架来开发还是挺不方便的,比如:

  • 不支持 npm 包

  • 不支持各种 CSS 预编译器

  • 不支持配置 Babel 来转换一些 JavaScript 新特性

这样一来和日常开发前端页面的体验相比来说,简直就像在刀耕火种。

那么为了解决这些问题,我们能不能将前端开发中常用的 webpack 移植到小程序开发中呢?

当然可以!

https://img1.sycdn.imooc.com//5b7581510001c2a107730661.jpg

0.源码地址

https://img1.sycdn.imooc.com//5b7581680001253402840119.jpg

  • 在 webpack-simple) 中文件结构和小程序相似。

  • 而在 webpack-vue) 中还增加了 vue-loader,因此你甚至还能利用 .vue 文件编写单文件组件。

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
  • app/: 应用入口

  • assets/: 资源文件,比如图片

  • comps/: 组件

  • pages/: 页面

  • scripts: 公用代码

  • scripts/const: 常量(已配置别名 @const)

  • scripts/utils: 辅助函数(已配置别名 @utils)

  • styles/: 公用样式

  • templates/: 模板

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 └── templates     └── info.wxml

1.3.整个项目文件结构大概长这样:

. ├── README.md ├── dist/ ├── package.json ├── project.config.json ├── src/ ├── webpack.config.babel.js └── yarn.lock
  • src/: 源码

  • dist/: 打包后代码

2.webpack 基础配置

2.1.entry/output

小程序场景下的配置应该是多入口,主要分为 apppagescomps 这三类。

  • app: 将 src/app/ 下的文件编译成 dist/ 根目录下的 app.js/app.json/app.wxss

  • pages: src/pages/ -> dist/pages/

  • comps: src/comps/ -> dist/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-...

2.2.CommonChunk

在 webpack 4 中有一个 breaking change,即使用 SplitChunksPlugin 替换了之前很常用的 CommonsChunkPlugin

主要提取了三部分的公共代码:

现在又碰到个新的问题:如何引入这些 chunks

在前端项目中一般我们通过 HtmlWebpackPlugin 插件在 html 文件中添加 <script> 标签引入,然鹅小程序中并没有 html 文件...

计将安出?

总不能每次都手动去 dist/app.js 中 require 这些文件吧?

这时候就要介绍另一款插件了~:BannerPlugin

这个插件本来是用在文件头部添加 banner 的,但是也支持插入代码,因此利用这款插件我们就可以将这些公共依赖在 app.js 中统一引入一次即可。

TODO: 现版本的小程序提供了分包加载能力,因此这里还有优化空间

2.3.CopyWebpackPlugin

顾名思义,这款插件的用处就是拷贝,利用这款插件我们就可以实现:

  • 复制 *.json

  • 复制 *.wxml

  • 复制 *.wxss

  • 复制 assets/

  • 复制 templates/

在使用时有一个知识点可以减少代码量:即 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。

在 v15 中,<style> 会完成把它当作一个真实的 *.less 文件来加载。因此,为了这样处理它,你需要在你的主 webpack 配置中显式地提供一条规则。

简单来说就是咱们之前配置过的各个预处理器规则会被 vue-loader 自动使用。

因此我们只需要简单地添加一条规则即可读取 .vue 文件:

{     test: /\.vue$/,     exclude: /node_modules/,     loader: 'vue-loader',     options: {         compiler: {             // mock vue-template-compiler             compile: () => ({                 staticRenderFns: [],             })         },     }, },
options.compiler 是啥?

3.2.options.compiler

options.compiler 覆写用来编译单文件组件中 <template> 块的默认编译器。

在实际使用单文件组件时,我们通过 <template> 来包裹原本的 .wxml 文件中的内容。

因为最终要编译成 .wxml 文件才能被开发者工具识别,所以我们还编写了一条规则通过 file-loader 生成最终的 .wxml文件:

{     // 处理 <template>{...}</template>     // 生成 .wxml 文件     test: /\.wxml$/,     use: {         loader: 'file-loader',         options: {             name: getNameByFilePathAndExt('.wxml'),         },     }, },

但是因为 vue-loader 默认会编译 template 中的内容将其生成一个个 render 函数。但其实在小程序场景中我们并不需要这一步骤。我们只想安安静静地将这些代码通过 file-loader 生成 .wxml 文件...

幸好 vue-loader 还提供了 options.compiler 这个参数用来传递自己的编译器。所以这里其实是 mock 了一下 vue-template-compiler

3.3.Custom Blocks

最后还有个问题没有解决:如何处理 .json 文件?

在其他的小程序框架中是这样处理的:

  • 在 wepy 中将其作为组件的 config 属性

export default class Index extends wepy.page {     //页面配置     config = {         "navigationBarTitleText": "test"     };     // ... }
  • 在 mpvue 中是写在 main.js 的输出部分

// main.js export default {   // 这个字段走 app.json   config: {     // 页面前带有 ^ 符号的,会被编译成首页,其他页面可以选填,我们会自动把 webpack entry 里面的入口页面加进去     pages: ['pages/logs/main', '^pages/index/main'],     window: {       backgroundTextStyle: 'light',       navigationBarBackgroundColor: '#fff',       navigationBarTitleText: 'WeChat',       navigationBarTextStyle: 'black'     }   } } // src/pages/logs/main.js export default {   config: {     navigationBarTitleText: '查看启动日志'   } }

在 tua-mp 中目前采用的是自定义块的方式来实现的,即在 .vue 文件中新增了一个 <config> 块来编写配置。

<config> {   "navigationBarTitleText": "查看启动日志" } </config> <template>     ... </template>

但是并没有将 app.json 的内容放到 App.vue 中,因为有时需要读取这里的页面配置。如果写到 <config> 中的话,就无法读取了...

例如为了实现从分享后的页面后退返回首页这个功能,在辅助函数中就需要读取页面和 tabBar 配置,生成分享链接(实际分享地址是首页,然后从首页再导航到被分享的页面)。

因此最优解是页面配置写在 <config> 中,应用配置写在 app.js 的输出中。

TODO: 实现 mpvue 的方式处理 app.json

具体的配置如下:

{     // 处理 <config>{...}</config> 代码块     // 生成 .json 文件     resourceQuery: /blockType=config/,     use: {         loader: 'file-loader',         options: {             name: getNameByFilePathAndExt('.json'),         },     }, },

4.总结

综上,咱们在 webpack v4 和 vue-loader v15 的帮助下,让小程序拥有了以下能力:

  • 加载 npm 包

  • 提取 CommonChunk 减少打包体积

  • babel 编译 JavaScript 代码

  • 支持 less/sass/stylus 等预处理器

  • 单文件组件

不过话又说回来了...

原生的小程序...又不是不能用~

注:这句话是黄章说的,Teacher Luo 没说过这话哟~

以上 to be continued...

原文链接:https://segmentfault.com/a/1190000015978833

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消