收藏
评论

JS代码的分包异步化官方


你好,我是李艺。

上节课我们主要学习了主页中使用占位组件以及封面化的优化技巧,这节课我们学习JS代码的一个分包异步化。

首先我们看一下问题,小程序提供的分包异步化能力不仅针对组件代码,插件也可以异步化一言以蔽之,另一个分包内的一切,只要我们想使用,都可以通过异步加载的方式拿过来使用。


接下来我们看项目实践一 异步加载另一个代码包里面的JS。

在目前我们的index_addons分包里面可以创建一个get_nav_list.js这样的一个文件,将这个文件作为一个模块,提供getNavList这样的一个方法,稍后我们将调用这个方法获取导航的列表数据,在主页的JS文件里面,在周期函数onReady这个函数里面可以使用require.async方法异步加载,get_nav_list.js这个文件里面的代码,并且在加载完成以后去使用它,主页位于index代码包里面,而get_nav_list.js这个文件位于index_addons代码包里面,这是在一个代码包里面加载并使用另一个代码包里面的JS代码。

接下来我们看实践一的代码演示。

为了测试,首先我们要在一个代码包里面去创建一个JS文件,这个文件我们需要导出一个方法,就是getNavList,这个方法会给我们提供我们一个页面里面所需要的导航信息全部都是静态内容,不需要去后端然后加载接口,这个文件然后准备好了以后,接下来我们还需要在另外的一个文件里面,就是在index主页所在的代码包里面去加载我们的新添加的文件,并且去调用里面的导出的方法,这是我们要做的一个事情。

这是现在的项目所在的一个状态,刚才我们看到那个是最终的一个源码,现在我们先确认一下在我们当前的这个项目里面,刚才所说的文件它是不是存在,这个地方还没有,没有没关系,我们进行一个创建,这是名称,这个名字我们复制一下直接放在index_addons的目录的一个下面,将这个代码拷贝过来,接下来我们再看它的一个调用代码,查看一下在首页里面对它的一个调用。

在这个地方有一个测试分包中JS代码的异步化加载与执行,这个代码我们要放在这个onReady的最后面进行调用,代码已经放进来了,这个里边有两种方式,第一种方式,这是我们使用本身小程序它已经提供的一种方法就是require.async,然后给它一个相对地址,这个地址是我们在这个位置能访问到的,我们刚才创建的这样的一个文件,这个文件里面其实已经有了,在这个里面已经有这个文件了,我们把外边这个文件给它去掉,里边这已经有了,在components子目录下面去加载这个文件,加载完成以后,拿到以后,因为我们这个地方会有一个await,这个地方有一个async,拿到这个结果以后,这个地方有一个解构命名,把它命名为getNavList,因为在我们的文件里面用的语法是ESModule,就ES6的模块规范,它会有一个default导出,所以我们在这个地方要有一个结构命名,将default命名为getNavList。

这一步走完以后,接下来我们会调用它拿到NavList,拿到以后,将列表赋值给我们的data,data里面就这样的一个对象,赋值给它,代码已经搞完了 现在我们单击编译测试一下,已经显示了,在调试区我们可以看到分包异步化拿到了本地导航数据,其实就是在我们刚才这个代码里面的一个打印,说明它已经走到这一步了,我们navs因为不止在一个地方有设置,另外还有一个对后端接口的调用设置,所以即使我们后面不成功的话,前面它也是可以将导航信息进行设置的,这个代码演示就到这里。


下面我们看实践二 定义使用绝对路径的require和requireAsync方法。

分包异步化在用的时候,用到了require和require.async方法,它们的参数都不支持绝对路径,只支持相对路径,这个相对路径它不方便我们拷贝代码,如果我们在这个页面A里面写了一段模块引入的代码,想拷贝到页面B里面去使用,由于这两个页面它路径的深度可能是不一样的,我们直接拷贝这个代码,路径可能就会报错,使用绝对路径就没有这个问题了,为了解决这个问题,可以在这个项目的主代码文件,也就是app.js这个文件里面定义两个支持绝对路径的方法,代替默认的require以及require.async这两个方法,代替它们加载分包异步化的模块或者是普通模块。

有了这两个方法以后,在主页面的JS文件里面就可以使用另外的一种绝对路径加载另一个代码包里面的模块了,修改以后这个代码可以看到它们的作用是相同的,区别就是这个路径不太一样,但是这个地方有个问题我们需要注意一下,在使用require关键字的时候,有时候我们不能使用变量作为路径,很重要,有时候我们使用变量作为路径,可能会导致我们这个代码不能正常运行,而且这种情况下也没有任何的提示,所以这种错误很难发现。这个时候我们就需要老实一点,该使用相对路径就改用这个相对路径就可以了。

接下来我们看实践二的代码演示。

这两个方法我们需要写在我们程序的主文件里面,也就是app.js里面,为什么要写在这个地方,因为只有在这个文件下面取路径的时候才可以以绝对路径去取我们项目下的文件,因为本身这个文件就是在我们这个项目的根目录下,同时这个文件它也是我们小程序的一个入口文件,也是首先执行的,如果是你要做一些hack 一些劫持,最好放在这个文件下,这个地方有我们之前已经写好的代码,将这个代码可以反注释一下,一共是两个,一个是require,另外一个是requireAsync,在这个地方我们可以注意到,里面有关于path路径的一个设置,这个设置不要也可以 ,如果有的话可以让我们在这个路径里边以斜杠作为开头,如果你不用的话,那就是不要斜杠,去掉就可以了,这个方法现在已经有了。

接下来我们测试前面已经写的JS异步化的代码,找到我们这个代码,这个地方,然后将下面这个代码给它注掉,把上面这个代码给它打开,可以看到它们的区别,前面是一样的,await也是一样的,这个地方我们用getApp然后取到程序实例的一个引用调用它的requireAsync,就是异步去加载,这,可以加一个斜杠,用这个绝对地址,这个地址就是一个绝对地址,这种写法我们放在另外的一个文件里面其实也是适用的,因为它没有这种相对路径的一种烦恼,这个代码已经改完了,我们单击编译看一下它的运行效果。看到没有,分包异步化拿到了本地导航数据,说明我们已经执行完成了,但是刚才我们提到了,因为我们在这个方法的定义和使用过程当中是将它本身要用到的path以变量的形式提供了,这种方式可能会让我们的代码产生一些未知问题,所以为了保险起见,这两个方法我们暂时还是不用为好,你知道有这种用法就可以了。但有些项目的时候其实它还是可以使用的,有些不行,我们代码演示就到这里。


下面我们看实践三,项目插件化。

下面我们准备实现插件的里边的JS代码的一个分包异步化加载,在此之前我们需要在本地添加一个插件目录并且将我们这个项目改造为插件的开发模式,普通小程序项目像插件开发模式改造很简单,只需要创建一个plugin目录,然后修改这个项目的配置文件,将这个编译类型由原来的miniprogram改为plugin就可以了,完成以后我们还要记得重启项目,因为你如果不重启的话,这个项目配置文件可能会不生效。

有一点在这里我们需要注意,这个项目模式改变以后,在私有的项目配置文件,这个地方是私有的项目配置文件,不是我们前面的项目配置文件,它的名字是project.private.config.json,里边多了一个private,原来自定义的编译模式没有了。实际上它也不是没有,只是换了一个地方,由原来的condition/miniprogram这个节点移到了condition/plugin这个节点下面,它里面的配置信息其实是一样的,如果是我们想复用原来的那些编译模式的话,可以直接将这些设置信息拷贝过去就可以复用了。

除了可以在工具栏里面通过手动操作添加这些编译模式,直接修改私有的项目配置文件,前面我们提到的一样,重启项目也是可以达到同样的一个目的。在小程序这个项目里边一共有三个配置文件需要理清一下,第一个就是app.json,它是运行时的项目配置文件;第二个project.config.json,它属于开发配置;第三个project.private.config.json,它属于私有的项目开发配置,我们可以把它看作是我们前面的项目配置文件的一个补充,这三个文件里面只有app.json文件,会打包在我们最终的代码包里边,另外的两个项目配置文件则不会,修改完成以后重新导入项目,小程序就可以正常的运行了,下面我们看代码演示。

现在我们开始实践三的代码演示。

先明确一下我们目前的项目它的一个编译模式,打开项目配置文件可以看到这个地方有一个compileType等于miniprogram,现在我们将这个文件,将这个项目先关掉,因为如果我们不关掉的话,可能会影响它,这个地方也可以修改,比如说我们将这个直接改成插件模式,改完以后我们可以看到这个地方已经变化了,compileType等于plugin了,但是我们现在plugin的这个目录还没有,需要创建一个目录,在最终的源码里面,这个地方是有一个plugin目录,这是我们要使用的一个代码,我们将这个代码给它拷贝一下,当然我们在VSCode里面也可以直接拷贝,拷贝以后到我们这个目录里面去,这个是我们的一个现在正在使用的一个目录,然后放在这个地方,而这个文件其实就刚才我们在微信开发者工具里面看到的一个配置文件,其实它俩是一样的,这样已经有了。

如果要使用这个插件的话,还有一步就是我们需要一个引入,这个引入有全局引入还有代码包,某一个代码包的引入,两种方法都是可以的,接下来是为了测试这个插件的分包异步化,所以我们要把它放在某一个代码包里边,我们看一下最终的项目配置,这个里面还没有,我们需要的关于plugin的一个配置信息是不是没有,在这个index_addons里面,有这个信息,我们需要将这个信息放在我们的app.json,找到我们目前的index_addons代码包,然后放在这个地方,这个名字是自定义的,稍后我们会用到它,你换到另外的一个名字也是可以的,然后版本是dev代表的是开发模式,这个是我们当前的小程序账号,这个是我们导出的一个文件index.js,这个文件在我们plugin这个目录下面也是存在的,其实是这样的一个文件,这里面有一个getPluginVersion这样的一个方法,稍后我们会调用这个方法,这就完成了我们项目的一个插件化了。

现在我们重启一下,pluginRoot不能为空,我们看一下,出现了一个错误,它提示也太强了,就这样、保存、覆盖以后,我们要把我们这个项目重启一下,重新打开一下我们这个项目,让它可以再次读取我们这个项目配置文件,已经重新启动了,现在还在启动中,现在我们这个项目已经是插件的一个开发模式了,这个地方我们需要注意一下,这个地方在编译模式这个地方可以点开看一下,我们原来所有的那些自定义的编译模式都没有了,跑到哪里去了为什么没有了,它其实不是没有了是换了一个地方,就是我们这个地方,我们原来配置它这个节点,在miniprogram这个下面,这是我们定义的对不对,现在它这个节点变成了一个plugin,可以把这个给它改成这个 加一个这样 然后将这个里面 它不让我直接加,我就把这个项目关掉以后可以在VSCode里面直接修改,找到我们的当前的项目目录,在这个地方修改,然后把这个改一下将我们的list,所有的这些自定义的数据拷贝到这个地方,完成以后再打开我们微信开发者工具,再次打开我们这个项目,又启动了,看一下我们配置文件,添加的配置是不是还在,没关系还在。

看一下编译模式,这些编译信息又回来了,在我们改成这个插件模式以后,这些配置信息它只是换了一个地方,并没有本质上丢失,但是在这个地方我们有一个问题,稍后我们也会看到这个代码依赖分析,这个地方只有一个主包了,其他的分包信息都没了,而且主包大小也不对,显示358B,这个大小肯定是不对的,因为实际上我们现在这个项目里面有很多的代码分包都是存在的,这个代码演示就到这里。


下面我们看实践四,插件中JS代码的分包异步化。

我们将这个插件代码放入到plugin目录以后,这个目录下有一个主文件就是index.js,这个文件里面特意有一个导出的代码,它导出了一个名称为getPluginVersion的方法,这个方法是为我们下一步测试用的,在这个测试开始之前还需要在app.json配置文件里面,也就是在分包index_addons这个节点里面添加插件的引入信息,插件的引入可以全局的引入,也可以在某个代码包里面进行引入,在这里我们为了测试这个插件里面JS代码的分包异步化,所以要将它放在index_addons这个代码包里面,这是我们为了完成我们测试的需要,在配置完成以后接下来就可以在我们这个页面代码里面实现插件代码的一个分包异步化的一个加载了,本质上这种分包异步化跟我们前面的JS代码的分包异步化很像,它只是我们调用的这个方法不太一样,前面我们调用那个方法是require还有require.async,插件这个地方我们调用的是requirePlugin以及requirePlugin.async,它这个名称不太一样,另外它第一个参数也不一样,前面我们使用的是相对地址,在这个地方我们将要使用在配置文件里面自定义的插件的名称myPlugin,这个地方我们要注意一下,关于插件异步加载的这两个方法requirePlugin和requirePlugin.async,因为它们使用的是配置文件里边,我们已经定义好的插件名称,使用的不是路径,所以也没有必要再进行重写了,下面我们看代码演示。

现在我们开始实践四的代码演示。

首先现在我们要确认一下我们要使用的要加载的插件里面的代码,它位于plugin index.js这个文件里面,这个就是最终我们要调用那个方法,这个方法很简单,它只是返回一个版本号

接下来这个有了以后还需要确认在这个项目的配置文件里边,在这个代码包里面已经对它有了一个引入,对这个插件有了引入,同时插件名称也具备了 叫myPlugin,再往下就是我们要写测试代码,在主页的JS文件里边,在这个地方我们要加测试代码,看一下我们最终的代码,在主页的JS文件里面 在onReady下面这个地方,测试插件中JS代码的分包异步化,将这段代码拷贝一下放在这个地方。

这个地方我们注意其实这是两种调用方式,第一种是用回调的方式,将一个回调函数然后作为参数传递给它,然后第二种这个是另外的一种就是async这样的一种调用方式,当然这种方式我们还可以再进一步地再改变一下,比如说我们这个地方用立即执行函数,为什么要用立即执行函数稍后我们会细讲,因为我们现在这个测试代码位于我们小程序启动流程的一个主线上,为了不阻碍我们主线的一个执行,所以如果我们在这个上面去使用async关键字的话,必须把它放在一个安全的地方,相对安全的地方,这个地方我们就可以获取它的一个结果了,结果我们还可以做一个什么,它只是导出对吧,其实它这个地方是没有default的,等于它后面这个结果可以拿出来,放在下面,这个就可以去掉,但为了安全起见可以加一个catch,这种写法也是可以的。

上面这是另外一种写法,我们实现的功能是类似的,代码已经写完了,现在我们单击编译看一下它的运行效果,我这台电脑的配置不太可以,如果你们可以尽量要用高配置的电脑,因为我这个电脑在开了录屏以后明显感觉到开发者工具就比较卡,有时候风扇狂转,这个地方我们看到插件版本1,插件版本2 它都有一个版本的打印对不对,后面那个是我们通过这个方法调用取到的结果,这两种方式目前在我们这个地方都已经全部调用成功了,代码演示就到这里。


下面我们看实践五,去插件化解决静态依赖分析不显示的问题。

将项目改为插件模式以后影响的不仅是配置文件的内容,像我们前面看到关于编译模式配置,它节点信息就已经发生变化了,原来可以运行的静态分析,依赖分析这个工具也不太好用了,解决这个问题的关键就是我们可以去插件化,将我们这个项目重设为小程序的一个开发模式,如果这个项目里边真正的用到的这个插件的话,我们可以使用这个插件的非开发模式,也就是引用线上已经发布的一个公开插件,下面我们看代码演示。

下面看实践五的代码演示。

去插件化最保险的一个问题,就是我们要第一步先把我们微信开发者工具先给它关了,关了以后打开我们VSCode,VSCode里面plugin这个目录我们可以保留,只要我们不使用它就可以了,项目配置文件把编译类型给它改成miniprogram,改一下,这个不需要了,另外还有一个是我们关于插件的一个引入,插件的引入是在index_addons 在这个地方,这个也不需要了 删掉,还有一个我们页面里面主页JS文件里面,测试代码,在这个地方,测试代码为了方便你后续做测试,我们只是将它注释掉,你使用的时候只需要将它反注释就可以了,这个已经改完了,接下来我们再重新打开我们小程序项目,这个地方既然没有自动切换,我们手动把它给它切换过来,项目已经启动了。首先看一下编译模式,这些都还在又回来了,接下来我们再看一下文档管理器里面的静态依赖分析,现在我们看到这里面我们所有的分包也已经回来了,而且静态依赖分析这个文件现在也可以正常工作了,代码演示我们就说到这里。


最后我们总结一下,分包异步化既可以实现组件的异步加载也可以实现JS代码,插件中JS代码的一个异步加载,有了分包我们可以尽最大的努力将主包尽可能的缩小,将主包的加载时间降到最低,有了分包异步化,我们又可以在主包里面使用拆分至分包里面的这些组件JS代码以及插件里面的JS代码。这节课我们就讲到这里,现在我们屏幕上显示的是我们这节课涉及到的文档地址。

点击查看开放文档:


这节课我们主要学习了代码的分包异步化以及插件代码的分包异步化,下节课我们学习如何使用WebAssembly技术优化代码性能。

最后我们看一下思考题,这里有个问题请你思考一下,JS这门语言的解析执行效率一直被人诟病,在小程序开发里面,有没有可能用Go语言或者是其他的C C++等这些编译性语言编写某些逻辑代码,这个问题先留给你思考一下,下节课我们一起来深入探讨一下这个问题。

最后一次编辑于  2022-07-14
赞 3
收藏

1 个评论

  • 草莓精
    草莓精
    2023-05-06

    跟流水账似的

    2023-05-06
    赞同 2
    回复
登录 后发表内容

小程序性能优化实践

课程标签