mocha-webpack
mocha-webpack copied to clipboard
Is it possible to use the DllReferencePlugin with mocha-webpack?
This kind of thing...
const vendorDll = paths.project.dll('vendor.dll.js');
...
const child = spawn(
'node',
[
mochaWebpack,
'--opts', mochaOptsPath,
'--colors',
'--webpack-config', testConfig,
'--require', vendorDll,
'--require', 'source-map-support/register',
'--require', setup,
testGlob
],
...
);
module.exports = {
target: 'node',
externals: [nodeExternals()],
plugins: [
new webpack.DllReferencePlugin({
context: paths.project.dll(),
manifest: require(paths.project.dll('vendor.manifest.json'))
}),
],
Anyone, Bueller?
I'm not entirely sure I understand what you're trying to do, but we're using DllReferencePlugin
in a project I'm working on and we didn't have to do anything special to get i working, just using the --webpack-config
option.
I'm trying to get this to work too, but seems to be something I'm missing. I get errors saying that the variable that the DLL bundle exports (and that the main bundle is looking for) is undefined, like:
ReferenceError: cesiumDll_7a13ade5de4dfdb862be is not defined
Just tried several different approaches to getting the DLL bundle loaded into the test code's global namespace, including require()
ing it, using --require
and --include
as CLI args, etc, with no luck.
Any tips?
May I ask you why you need to use DLL bundles with mocha-webpack? I always thought that it's recommended for bundling node_modules.
The main point of DLL bundles is to remove the need for Webpack to always process a given set of files, as well as build cacheable artifacts. I'm using the Cesium 3D globe library, which is a very large library (the bundle is around 2MB minified). At the moment, I'm pretty sure that the basic mocha-webpack test setup is having to process all of Cesium when it does compiles for tests, and I'd like to see if I can avoid that.
My recommendation is to completely avoid bundling node_modules with webpack's externals option. That's the fastest option.
But if this doesn't work for your library, then is DLL probably the way to go.
We're using Webpack DLL on our project and they are a must when your project scales.
You first need to create the DLL, then when you start/test/coverage/build your app, some part of the Webpack generation is already saved on disk (minified, dead code removed...).
It's perfectly working with mocha-webpack. Just use a DLLReferencePlugin on your webpack test file and it should work.
Another ways to improve compilation time are :
- enable cache on babel
- prefetch some class using webpack.PrefetchPlugin and the webpack stats analyser
And of course DLLPlugin
Yeah, per my comment, "just adding DLLReferencePlugin
" is not working :( I definitely have the DLL bundle on disk, but when I try to run a test, there's a JS error saying that the bundle export variable isn't defined. Not sure what I'm missing there.
Do you have a configuration file webpack.test.config.js
like that ?
{
target: 'node', // in order to ignore built-in modules like path, fs, etc.
externals: [nodeExternals({
// this WILL include these in the bundle
whitelist: [/react-material-color-picker/],
})],
// Enable sourcemaps for debugging webpack's output.
devtool: 'inline-source-map',
stats: {
chunks: false,
colors: true,
reasons: true,
},
module: {
noParse: [
/sinon/,
/iconv-loader/,
/enzyme/,
],
},
plugins: [
new webpack.DllReferencePlugin({
// The path to the manifest file which maps between
// modules included in a bundle and the internal IDs
// within that bundle
manifest: require(`${__dirname}/my-manifest.json`),
context: __dirname,
})
],
// enable sourcemaps support
output: {
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]',
},
}
My command in the package.json
"test:mocha": "mocha-webpack --timeout 20000 --webpack-config webpack.test.config.js \"@(tests|modules)/**/*.test.js{,x}\" --inline-diffs",
Edit: you have defined context: paths.project.dll(),
but It should be the root directory of your app
I was able to find a solution for this, using the node-hook
library. Here's the implementation:
/* HACK
This next chunk of setup is a _really_ nasty hack, but we need it to sucessfully
use the prebuilt DLL bundles with our third-party libs in our tests.
The problem is that the DLL bundles look like this:
var abc123 = function() {
// bundle contents here
};
When our application code runs, Webpack expects that "abc123" will be a variable
in the global namespace so that it can initialize the bundled code. However, when
run under Node, that module is isolated, so "var abc123" will _not_ be added to the
global namespace.
Here's the workaround:
1) Read the Webpack-generated manifest files for the bundles, and read out the "name"
field, which gives us the expected global variable name
2) Use a lib that hooks into Node's file resolution process, and gives us the actual
source code of the module after it's been read off disk. We can then add a new line
of code that exports the variable as the default export of the module.
3) Import each DLL bundle and save a reference to the contents
4) Turn off the require hook
5) Add the imported bundle function into the "global" object that will become the
actual global namespace when the application code is run in the test.
Ugly? Yep. Does it work? Yep :)
*/
const vendorManifest = require("../distdll/vendor-manifest.json");
const vendorBundleName = vendorManifest.name;
const nodeHook = require("node-hook");
nodeHook.hook('.js', function(source, filename) {
const newSource = `${source}\n\nmodule.exports = ${vendorBundleName};`;
return newSource
});
const vendorExport = require("../distdll/vendor.dll");
// Temporarily disable console logging to quiet nodeHook
const {log} = console;
console.log = () => {};
nodeHook.unhook('.js');
// reenable console .logging
console.log = log;
global[vendorBundleName] = vendorExport;
With this in place, my tests can now use the actual bundled libs from the DLL bundle.
when you're generating your DLL bundle, can you set libraryTarget
to commonjs2
or umd
? it should eliminate the need to worry about this. I might be missing something however what you're describing seems to be related to the fact that the DLL reference has some mismatch with the bundle it is referencing.
No, you can compile your DLL correctly (it works when used with webpack-dev-server) but while testing it fails to import it. It happens too on webpack-dev-server, it fails to import it suddently while it worked for last 20 runs.
So we're not using DLLReference while testing anymore (with >2K tests).