欢迎来到258分享网,纯净的网络源码分享基地!

258资源分享网

全部作品
全部作品
网站源码
微信源码
素材特效
源码插件
视频教程
建站学院
热门搜索: 织梦  农业种植  农业  安全设置  官方
258资源分享 > 建站学院 > 微信开发 > 小程序打包插件开发体验

推荐下载

HTML5响应式自适应网咯设计

2020-05-12   浏览:740

高端HTML5响应式企业通用网

2020-05-06   浏览:521

html5响应式外贸网站英文版

2020-05-08   浏览:510

HTML5自适应律师工作室类网

2020-04-04   浏览:504

HTML5影视传媒文化公司类网

2020-05-12   浏览:502

小程序打包插件开发体验

发布时间:2020-10-13  

相信开发过插件的同学,都看过Writing a Plugin 或类似的文章,因为 mini-program-webpack-loader 这个工具开发时正好 webpack 4 发布了,所以就阅读了这篇文章,顺便看了以下几篇文档。

如果你看过文档,相信你一定知道:

每个插件必须要有 apply 方法,用于 webpack 引擎执行你想要执行的代码。

两个重要的对象 Compiler 和 Compilation,你可以在上面绑定事件钩子(webpack 执行到该步骤的时候调用),具体有哪些事件钩子可以阅读Compiler hooks。

module 和 chunk 的关系,我们可以理解为每个文件都会有一个 module,而一个 chunk 则是由多个 module 来组成。

webpack 整个打包流程有那些事件

如何写一个简单的 loader

如果感觉无从着手,可以继续看看我是如何一步步开发并完善 mini-program-webpack-loader 来打包小程序的。

小程序有一个固定的套路,首先需要有一个 app.json 文件来定义所有的页面路径,然后每个页面有四个文件组成:.js,.json,.wxml,.wxss。所以我以 app.json 作为 webpack entry,当 webpack 执行插件的 apply 的时候,通过获取 entry 来知道小程序都有哪些页面。大概流程像下面一张图,一个小程序打包插件差不多就这样完成了。

小程序打包插件开发体验

这里使用了两个插件 MultiEntryPlugin,SingleEntryPlugin。为什么要这样做呢?因为 webpack 会根据你的 entry 配置(这里的 entry 不只是 webpack 配置里的 entry,import(), require.ensure() 都会生成一个 entry)来决定生成文件的个数,我们不希望把所有页面的 js 打包到一个文件,需要使用 SingleEntryPlugin 来生成一个新的 entry module;而那些静态资源,我们可以使用 MultiEntryPlugin 插件来处理,把这些文件作为一个 entry module 的依赖,在 loader 中配置 file-loader 即可把静态文件输出。伪代码如下:

const MultiEntryPlugin = require('webpack/lib/MultiEntryPlugin'); const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin'); class MiniPlugin { apply (compiler) { let options = compiler.options let context = compiler.rootContext let entry = options.entry let files = loadFiles(entry) let scripts = files.filter(file => /\.js$/.test(file)) let assets = files.filter(file => !/\.js$/.test(file)) new MultiEntryPlugin(context, assets, '__assets__').apply(compiler) scripts.forEach((file => { let fileName = relative(context, file).replace(extname(file), ''); new SingleEntryPlugin(context, file, fileName).apply(compiler); }) } } 复制代码

当然,如果像上面那样做,你会发现最后会多出一个 main.js,xxx.js(使用 MultiEntryPlugin 时填的名字),main.js 对应的是配置的 entry 生成的文件,xxx.js 则是 MultiEntryPlugin 生成的。这些文件不是我们需要的,所以需要去掉他。如果熟悉 webpack 文档,我们有很多地方可以修改最终打包出来的文件,如 compiler 的 emit 事件,compilation 的 optimizeChunks 相关的事件都可以实现。其本质上就是去修改 compilation.assets 对象。

在 mini-program-webpack-loader 中就使用了 emit 事件来处理这种不需要输出的内容。大概流程就像下面这样:

小程序打包插件开发体验

小程序打包当然没这么简单,还得支持wxml、wxss、wxs和自定义组件的引用,所以这个时候就需要一个 loader 来完成了,loader 需要做的事情也非常简单 —— 解析依赖的文件,如 .wxml 需要解析 import 组件的 src,wxs 的 src,.wxss 需要解析 @import,wxs 的 require,最后在 loader 中使用 loadModule 方法添加即可。自定义组件一开始在 add entry 步骤的时候直接获取了,所以不需要 loader 来完成。这个时候的图:

小程序打包插件开发体验

这样做也没什么问题,可是开发体验是比较差的,如再添加一个自定义组件,一个页面,webpack 是无感知的,所以需要在页面中的 .json 发生改变时检查是不是新增了自定义组件或者新增了页面。这个时候遇到一个问题,自定义组件的 js 是不能通过 addModule 的方式来添加的,因为自定义组件的 js 必须作为独立的入口文件。在 loader 中是做不了,所以尝试把文件传到 plugin 中(因为 plugin 先于 loader 执行,所以是可以建立 loader 和 plugin 通信的)。简单粗暴的方式:

// loader.js class MiniLoader {} module.exports = function (content) { new MiniLoader(this, content) } module.exports.$applyPluginInstance = function (plugin) { MiniLoader.prototype.$plugin = plugin } // plugin.js const loader = require('./loader') class MiniPlugin { apply (compiler) { loader.$applyPluginInstance(this); } } 复制代码

本文标签

: