We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
不同于 Vue 借助 webpack 是将 Vue 单文件最终打包成单独的 js chunk 文件。而小程序的规范是每个页面/组件需要对应的 wxml/js/wxss/json 4个文件。因为 mpx 使用单文件的方式去组织代码,所以在编译环节所需要做的工作之一就是将 mpx 单文件当中不同 block 的内容拆解到对应文件类型当中。在动态入口编译的小节里面我们了解到 mpx 会分析每个 mpx 文件的引用依赖,从而去给这个文件创建一个 entry 依赖(SingleEntryPlugin)并加入到 webpack 的编译流程当中。我们还是继续看下 mpx loader 对于 mpx 单文件初步编译转化后的内容:
/* script */ export * from "!!babel-loader!../../node_modules/@mpxjs/webpack-plugin/lib/selector?type=script&index=0!./list.mpx" /* styles */ require("!!../../node_modules/@mpxjs/webpack-plugin/lib/extractor?type=styles&index=0!../../node_modules/@mpxjs/webpack-plugin/lib/wxss/loader?root=&importLoaders=1&extract=true!../../node_modules/@mpxjs/webpack-plugin/lib/style-compiler/index?{\"id\":\"2271575d\",\"scoped\":false,\"sourceMap\":false,\"transRpx\":{\"mode\":\"only\",\"comment\":\"use rpx\",\"include\":\"/Users/XRene/demo/mpx-demo-source/src\"}}!stylus-loader!../../node_modules/@mpxjs/webpack-plugin/lib/selector?type=styles&index=0!./list.mpx") /* json */ require("!!../../node_modules/@mpxjs/webpack-plugin/lib/extractor?type=json&index=0!../../node_modules/@mpxjs/webpack-plugin/lib/json-compiler/index?root=!../../node_modules/@mpxjs/webpack-plugin/lib/selector?type=json&index=0!./list.mpx") /* template */ require("!!../../node_modules/@mpxjs/webpack-plugin/lib/extractor?type=template&index=0!../../node_modules/@mpxjs/webpack-plugin/lib/wxml/wxml-loader?root=!../../node_modules/@mpxjs/webpack-plugin/lib/template-compiler/index?{\"usingComponents\":[],\"hasScoped\":false,\"isNative\":false,\"moduleId\":\"2271575d\"}!../../node_modules/@mpxjs/webpack-plugin/lib/selector?type=template&index=0!./list.mpx")
接下来可以看下 styles/json/template 这3个 block 的处理流程是什么样。
首先来看下 json block 的处理流程:list.mpx -> json-compiler -> extractor。第一个阶段 list.mpx 文件经由 json-compiler 的处理流程在前面的章节已经讲过,主要就是分析依赖增加动态入口的编译过程。当所有的依赖分析完后,调用 json-compiler loader 的异步回调函数:
list.mpx -> json-compiler -> extractor
// lib/json-compiler/index.js module.exports = function (content) { ... const nativeCallback = this.async() ... let callbacked = false const callback = (err, processOutput) => { checkEntryDeps(() => { callbacked = true if (err) return nativeCallback(err) let output = `var json = ${JSON.stringify(json, null, 2)};\n` if (processOutput) output = processOutput(output) output += `module.exports = JSON.stringify(json, null, 2);\n` nativeCallback(null, output) }) } }
这里我们可以看到经由 json-compiler 处理后,通过nativeCallback方法传入下一个 loader 的文本内容形如:
nativeCallback
var json = { "usingComponents": { "list": "/components/list397512ea/list" } } module.exports = JSON.stringify(json, null, 2)
即这段文本内容会传递到下一个 loader 内部进行处理,即 extractor。接下来我们来看下 extractor 里面主要是实现了哪些功能:
// lib/extractor.js module.exports = function (content) { ... const contentLoader = normalize.lib('content-loader') let request = `!!${contentLoader}?${JSON.stringify(options)}!${this.resource}` // 构建一个新的 resource,且这个 resource 只需要经过 content-loader let resultSource = defaultResultSource const childFilename = 'extractor-filename' const outputOptions = { filename: childFilename } // 创建一个 child compiler const childCompiler = mainCompilation.createChildCompiler(request, outputOptions, [ new NodeTemplatePlugin(outputOptions), new LibraryTemplatePlugin(null, 'commonjs2'), // 最终输出的 chunk 内容遵循 commonjs 规范的可执行的模块代码 module.exports = (function(modules) {})([modules]) new NodeTargetPlugin(), new SingleEntryPlugin(this.context, request, resourcePath), new LimitChunkCountPlugin({ maxChunks: 1 }) ]) ... childCompiler.hooks.thisCompilation.tap('MpxWebpackPlugin ', (compilation) => { // 创建 loaderContext 时触发的 hook,在这个 hook 触发的时候,将原本从 json-compiler 传递过来的 content 内容挂载至 loaderContext.__mpx__ 属性上面以供接下来的 content -loader 来进行使用 compilation.hooks.normalModuleLoader.tap('MpxWebpackPlugin', (loaderContext, module) => { // 传递编译结果,子编译器进入content-loader后直接输出 loaderContext.__mpx__ = { content, fileDependencies: this.getDependencies(), contextDependencies: this.getContextDependencies() } }) }) let source childCompiler.hooks.afterCompile.tapAsync('MpxWebpackPlugin', (compilation, callback) => { // 这里 afterCompile 产出的 assets 的代码当中是包含 webpack runtime bootstrap 的代码,不过需要注意的是这个 source 模块的产出形式 // 因为使用了 new LibraryTemplatePlugin(null, 'commonjs2') 等插件。所以产出的 source 是可以在 node 环境下执行的 module // 因为在 loaderContext 上部署了 exec 方法,即可以直接执行 commonjs 规范的 module 代码,这样就最终完成了 mpx 单文件当中不同模块的抽离工作 source = compilation.assets[childFilename] && compilation.assets[childFilename].source() // Remove all chunk assets compilation.chunks.forEach((chunk) => { chunk.files.forEach((file) => { delete compilation.assets[file] }) }) callback() }) childCompiler.runAsChild((err, entries, compilation) => { ... try { // exec 是 loaderContext 上提供的一个方法,在其内部会构建原生的 node.js module,并执行这个 module 的代码 // 执行这个 module 代码后获取的内容就是通过 module.exports 导出的内容 let text = this.exec(source, request) if (Array.isArray(text)) { text = text.map((item) => { return item[1] }).join('\n') } let extracted = extract(text, options.type, resourcePath, +options.index, selfResourcePath) if (extracted) { resultSource = `module.exports = __webpack_public_path__ + ${JSON.stringify(extracted)};` } } catch (err) { return nativeCallback(err) } if (resultSource) { nativeCallback(null, resultSource) } else { nativeCallback() } }) }
稍微总结下上面的处理流程:
module.exports
所以上面的示例 demo 最终会输出一个 json 文件,里面包含的内容即为:
{ "usingComponents": { "list": "/components/list397512ea/list" } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
不同于 Vue 借助 webpack 是将 Vue 单文件最终打包成单独的 js chunk 文件。而小程序的规范是每个页面/组件需要对应的 wxml/js/wxss/json 4个文件。因为 mpx 使用单文件的方式去组织代码,所以在编译环节所需要做的工作之一就是将 mpx 单文件当中不同 block 的内容拆解到对应文件类型当中。在动态入口编译的小节里面我们了解到 mpx 会分析每个 mpx 文件的引用依赖,从而去给这个文件创建一个 entry 依赖(SingleEntryPlugin)并加入到 webpack 的编译流程当中。我们还是继续看下 mpx loader 对于 mpx 单文件初步编译转化后的内容:
接下来可以看下 styles/json/template 这3个 block 的处理流程是什么样。
首先来看下 json block 的处理流程:
list.mpx -> json-compiler -> extractor
。第一个阶段 list.mpx 文件经由 json-compiler 的处理流程在前面的章节已经讲过,主要就是分析依赖增加动态入口的编译过程。当所有的依赖分析完后,调用 json-compiler loader 的异步回调函数:这里我们可以看到经由 json-compiler 处理后,通过
nativeCallback
方法传入下一个 loader 的文本内容形如:即这段文本内容会传递到下一个 loader 内部进行处理,即 extractor。接下来我们来看下 extractor 里面主要是实现了哪些功能:
稍微总结下上面的处理流程:
module.exports
导出的内容。所以上面的示例 demo 最终会输出一个 json 文件,里面包含的内容即为:
The text was updated successfully, but these errors were encountered: