In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
Today, I would like to share with you the relevant knowledge of WeChat Mini Programs's method of packaging plug-in development. The content is detailed and the logic is clear. I believe most people still know too much about this, so share this article for your reference. I hope you can get something after reading this article, let's take a look at it.
If you have read the document, I am sure you know:
Each plug-in must have an apply method for the webpack engine to execute the code you want to execute.
Two important objects, Compiler and Compilation, on which you can bind event hooks (called when webpack executes this step), and which event hooks can be read Compiler hooks.
The relationship between module and chunk, we can understand that each file will have a module, while a chunk is made up of multiple module.
What are the events in the whole packaging process of webpack
How to write a simple loader
If I feel overwhelmed, I can continue to see how I developed and perfected mini-program-webpack-loader to package Mini Program step by step.
Mini Program has a fixed pattern, first you need to have an app.json file to define all the page paths, and then each page is composed of four files: .js, .json, .wxml, .wxss. So I use app.json as my webpack entry, and when webpack executes the apply of the plug-in, I know which pages Mini Program has by getting entry.
Two plug-ins MultiEntryPlugin,SingleEntryPlugin are used here. Why would you do that? Because webpack will determine the number of generated files according to your entry configuration (the entry here is not just entry,import () in the webpack configuration, require.ensure () will generate an entry), we do not want to package the js of all pages into one file, we need to use SingleEntryPlugin to generate a new entry module And those static resources, we can use the MultiEntryPlugin plug-in to deal with these files as an entry module dependency, configure file-loader in loader to output static files. The pseudo code is as follows:
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);})} copy the code
Of course, if you do as above, you will find that you will end up with an extra main.js,xxx.js (the name you fill in when using MultiEntryPlugin), main.js corresponds to the file generated by the configured entry, and xxx.js is generated by MultiEntryPlugin. These documents are not what we need, so we need to get rid of him. If you are familiar with webpack documents, there are many places we can modify the final packaged files, such as compiler's emit event and compilation's optimizeChunks-related events. The essence is to modify the compilation.assets object.
The emit event is used in mini-program-webpack-loader to handle this kind of content that does not require output.
Of course, Mini Program packaging is not that simple, but also supports references to wxml, wxss, wxs and custom components, so at this time you need a loader to complete, and what loader needs to do is also very simple-to resolve dependent files, such as .wxml to resolve the src,wxs of import components, you need to resolve the require of @ import,wxs, and finally use the loadModule method to add it in loader. The custom component is obtained directly at the beginning of the add entry step, so there is no need for loader to complete it.
There is no problem with this, but the development experience is relatively poor, such as adding a custom component and a page, webpack is not aware, so you need to check whether custom components or pages have been added when the .json in the page changes. At this time, there is a problem that the js of the custom component cannot be added through addModule, because the js of the custom component must be used as a separate entry file. You can't do this in loader, so try to transfer the file to plugin (because plugin is executed before loader, it is possible to establish loader and plugin communication).
In a simple and rude way:
/ / loader.jsclass MiniLoader {} module.exports = function (content) {new MiniLoader (this, content)} module.exports.$applyPluginInstance = function (plugin) {MiniLoader.prototype.$plugin = plugin} / / plugin.jsconst loader = require ('. / loader') class MiniPlugin {apply (compiler) {loader.$applyPluginInstance (this);}} copy the code
But.... The file is transferred to plugin, but when you use SingleEntryPlugin again, you will find that it has no effect. Since webpack can no longer perceive the addition of new module after compiler make, it is useless. At this time, you need to guess according to the document how to make webpack aware of the new module, and make keyword queries according to the events in the document. You can find that the compilation needAdditionalPass event hook will be called when the compilation is complete:
This.emitAssets (compilation, err = > {if (err) return finalCallback (err); if (compilation.hooks.needAdditionalPass.call ()) {compilation.needAdditionalPass = true; const stats = new Stats (compilation); stats.startTime = startTime; stats.endTime = Date.now () This.hooks.done.callAsync (stats, err = > {if (err) return finalCallback (err); this.hooks.additionalPass.callAsync (err = > {if (err) return finalCallback (err); this.compile (onCompiled)) ); return;} this.emitRecords (err = > {if (err) return finalCallback (err); const stats = new Stats (compilation); stats.startTime = startTime) Stats.endTime = Date.now (); this.hooks.done.callAsync (stats, err = > {if (err) return finalCallback (err); return finalCallback (null, stats);});}); copy code
If you return a true value in this event hook, you can make webpack call the compiler additionalPass event hook and try to add a file here, which is fine.
Of course, there are some differences in Mini Program packaging, such as subcontracting, how to make good use of splitchunk, is no longer verbose, when you start, you will find that there are many ways to achieve the desired results.
Plug-in development is almost done here. Generally speaking, webpack is just a fancy callback, and webpack is easy to use when you know what to do with each callback. Obviously I don't know, because I encountered some problems in the development process.
Problems encountered
1. How to support resolve alias,node_modules in Mini Program code?
Since it is a tool, of course we need to do more things, as complicated as the awesome Mini Program, if supporting resolve alias,node_modules can make the project more convenient to maintain, maybe you will say that this is not the most basic function of webpack, no, of course we hope that we can use alias,node_modules in any file to support not just js. Of course, this means that things will get complicated, starting with getting the file path, which must be asynchronous, because resolve no longer supports sync in webpack 4. The second is that the directory name of Mini Program cannot be node_modules, so you need a rule to calculate the relative path, which is relatively packaged and output, not relative to the current project directory.
two。 Merger of multiple Mini Program projects
As far as mini programs are concerned, there are WeChat merchant city version, retail version, and public version, most of which have the same basic functions and business, of course, you can't develop every Mini Program again, so it is certainly necessary for this tool to merge multiple Mini Program. Such a merge is slightly more complicated than fetching files from node_modules, because you need to ensure that multiple Mini Program merged pages are correct and that the path remains the same.
The final solution to these two problems is to take the src directory of webpack rootContext as the base directory, calculate the absolute path of the packaged file according to the path of the directory, and then calculate the final output path according to the path of the app.json directory of the entry file.
Exports.getDistPath = (compilerContext EntryContexts) = > {/ * webpack takes the src of the directory where the config is located as the packaging entry * so you can trace the source file address * / return (path) = > {let fullPath = compilerContext let npmReg = / node_modules/g let pDirReg = / ^ [_ |\.]\ / g if (isAbsolute (path)) {fullPath = path} else {/ / relative path: the last generated path of webpack according to this directory The files outside the packaging entry are represented by'_'in the parent directory while (pDirReg.test (path)) {path = path.substr (pDirReg.lastIndex) fullPath = join (fullPath,'.. /')} if (fullPath! = = compilerContext) {fullPath = join (fullPath, path)}} / / obtain the packaged directory according to the json file directory defined in entry If you cannot get it, return the original path let contextReg = new RegExp (entryContexts.join ('|'),'g') if (fullPath! = = compilerContext & & contextReg.exec (fullPath)) {path = fullPath.substr (contextReg.lastIndex + 1) console.assert (! npmReg.test (path), `File ${path} path error: it should not also contain node_ modules`)} / * * if there is a node_modules string Then remove the module name * if app.json is in node_modules, then path should not contain node_modules * / if (npmReg.test (path)) {path = path.substr (npmReg.lastIndex + 1)} return path}} copy code
3. How to package the contents that a subpackage depends on separately into a subpackage
The solution to this problem is to use the optimizeChunks event, add the entry file of the chunk to the dependent module of each chunk, and then check the number of module dependencies in the test configuration of the splitChunk. If there is only one, and the quilt package is dependent, it is packaged into a subpackage.
Failed to support single file for 4.webpack
This is an unsolved problem, and it doesn't seem so convenient when trying to use webpack to support single files:
After a single file is split into four files, you can use emitFile and addDependency to create the file, but the created file does not execute loader
Using loadModule will report an error because the file system does not exist.
These are all the contents of this article entitled "WeChat Mini Programs's method of Packaging plug-in Development". Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.