You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It is a way to run modules and get the exports at compile time, imagine you need to get some information at compile time, for example, in mini-css-extract-plugin, it needs build information of css-loader, however css-loader only passes javascript string to the next loader. So mini-css-extract-plugin will run the javascript at compile time using loaderContext.importModule, and get the actual CSS build info.
module, is the module you want to execute at compile time
options, some compile options
callback, this callback can be executed after the module gets executed
Build those modules
When executeModule begins, it adds the module into the Webpack internal build queue, and when it is built, adds the dependencies of it into the build queue as well. Note that if one module has been built already, it won't be built again, which means one module will only gets built once, so it is performant.
Process modules
In Webpack, module might needs extra runtime to make them work, every module has its runtime requirements after build, what is runtime requirements ? It's a list that indicates which runtime does this module needs. Every runtime is a module, for example, Webpack has runtime which can load script or styles, that runtime module will be something like
__webpack_require__.e = function() { ... }
So we need to get all the runtime modules of all the modules that need to execute.
Webpack reuse the function of how Webpack processes the runtime, in order to reuse that, Webpack create a brand-new chunk graph, use the new chunkGraph to calculate module hash, module codegen, and get module runtime modules. You can see more details here.
And then create a map to record module's assets. (this is not strongly needed
Execute
Finally we need to do execution. However not like Webpack, all the codegenResults info are stored at Rust side, so we need to transfer it to js side, and in js side, create a mock webpack_require, see here to check what's in it. The mock webpack_require is pretty simple, it looks the module code in the codegenerationResults, and just use node.js vm.runInThisContext to run the module.
First run all the runtime modules, ensure all the needed runtime are ready, then execute the entry, get the final exports results.
Implement
Most steps above are easy, but the final step, which is execution, is a little bit different. As we run build in native side, but we need the capability to execute JavaScript, and get the result of it. So we need to create runner in JavaScript.
JavaScript side needs to know all the code generation results, almost nothing else. Then invoke it and get the result. But there are some optimizations we should consider:
JavaScript should better not block native side
Multiple importModule calls better run concurrently
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
What is importModule ?
It is a way to run modules and get the exports at compile time, imagine you need to get some information at compile time, for example, in mini-css-extract-plugin, it needs build information of css-loader, however css-loader only passes javascript string to the next loader. So mini-css-extract-plugin will run the javascript at compile time using loaderContext.importModule, and get the actual CSS build info.
How does it work ?
it uses compilation.executeModule under the hood.
It receives 3 parameters:
Build those modules
When executeModule begins, it adds the module into the Webpack internal build queue, and when it is built, adds the dependencies of it into the build queue as well. Note that if one module has been built already, it won't be built again, which means one module will only gets built once, so it is performant.
Process modules
In Webpack, module might needs extra runtime to make them work, every module has its runtime requirements after build, what is runtime requirements ? It's a list that indicates which runtime does this module needs. Every runtime is a module, for example, Webpack has runtime which can load script or styles, that runtime module will be something like
So we need to get all the runtime modules of all the modules that need to execute.
Webpack reuse the function of how Webpack processes the runtime, in order to reuse that, Webpack create a brand-new chunk graph, use the new chunkGraph to calculate module hash, module codegen, and get module runtime modules. You can see more details here.
And then create a map to record module's assets. (this is not strongly needed
Execute
Finally we need to do execution. However not like Webpack, all the codegenResults info are stored at Rust side, so we need to transfer it to js side, and in js side, create a mock webpack_require, see here to check what's in it. The mock webpack_require is pretty simple, it looks the module code in the codegenerationResults, and just use node.js vm.runInThisContext to run the module.
First run all the runtime modules, ensure all the needed runtime are ready, then execute the entry, get the final exports results.
Implement
Most steps above are easy, but the final step, which is execution, is a little bit different. As we run build in native side, but we need the capability to execute JavaScript, and get the result of it. So we need to create runner in JavaScript.
JavaScript side needs to know all the code generation results, almost nothing else. Then invoke it and get the result. But there are some optimizations we should consider:
Beta Was this translation helpful? Give feedback.
All reactions