dialog: viewModel is not found by webpack
I’m submitting a bug report
- Library Version: 1.0.0-rc.1.0.3
Please tell us about your environment:
-
Operating System: Windows 10
-
Node Version: 6.10.3
-
NPM Version: 5.0.0
-
JSPM OR Webpack AND Version webpack 2.5.1
-
Browser: All
-
Language: TypeScript 2.3
Current behavior: DialogService is not finding my viewModel. It does not report the problem and instead puts up an entirely empty and invisible dialog.
I invoke .open
like this:
return this.dialogService.open(settings) ...
where settings.viewModel
is set like this:
import {Prompt} from "../resources/commonDialogs/prompt";
.
.
.
settings.viewModel = Prompt;
(Note: Prompt
is my own, not from the Aurelia-dialog example.)
DialogService sees the Prompt
viewModel function and tries to do something with it here:
DialogService.prototype.ensureViewModel = function (compositionContext) {
if (typeof compositionContext.viewModel === 'function') {
compositionContext.viewModel = __WEBPACK_IMPORTED_MODULE_1_aurelia_metadata__["Origin"].get(compositionContext.viewModel).moduleId;
}
if (typeof compositionContext.viewModel === 'string') {
return this.compositionEngine.ensureViewModel(compositionContext);
}
return Promise.resolve(compositionContext);
};
But WEBPACK_IMPORTED_MODULE_1_aurelia_metadata__["Origin"].get(compositionContext.viewModel).moduleId
returns undefined
.
All of the relevant code is contained in a vendor.js file generated by webpack.
Expected/desired behavior:
-
What is the expected behavior? Should find my viewmodel or else report an error. If there are additional steps that I’m not following, then they should be documented.
-
What is the motivation / use case for changing the behavior? Supplying a viewModel in the settings is supposed to work. I assume webpack is part of the use case as well.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 66 (20 by maintainers)
Not anytime, but very likely. If the module that contains your class is added to a concatenated module, then it won’t work.
@dkent600 I meant ES
import
a viewmodel that is then feeded as a ctor toaurelia-dialog
.With Webpack it creates unsolvable origin problems when using DLL and now when using
ModuleConcatenationPlugin
.Instead you should pass the module name, wrapped with
moduleName
.Using ES
import
in your code is fine. In fact it’s the module system I recommend when using Webpack to bundle your app (it supports advanced optimizations such asModuleConcatenationPlugin
, tree shaking or exports renaming).@dkent600 I’ll try to fix it.
OK, now we’re talking. It’s @niieani’s magic, but thankfully I understand that part well enough that I can explain.
Aurelia has a lot of reliance on the origin (module name) of resources (viewmodels & co.). As long as modules are loaded through
aurelia-loader
, they are tagged so that this works (it’s done insideaurelia-loader-webpack
).The issue arises when something that was not loaded through
aurelia-loader
is suddenly asked for origin by Aurelia. This happens very rarely, and the pattern above (import
ed VM foraurelia-dialog
) is the main occurrence of this.Before I even got started on the Webpack 2.0 plugin, @niieani had identified this issue and came up with the following solution: he would look at every loaded module for an export that matches the object whose origin is asked for. This is done here: https://github.com/aurelia/metadata/blob/master/src/origin.js#L37-L56
As you can see it relies on
PLATFORM.eachModule
. How do you iterate all modules? Well, it’s not part of the official API (it grabs directly at internals), butaurelia-loader-webpack
provides this implementation: https://github.com/aurelia/loader-webpack/blob/master/src/aurelia-loader-webpack.ts#L90-L100And this is where the limitation lies. At the time when @niieani did this we did not have DLL support, which I added later. If you have some familiarity with Webpack internals you understand that the code I linked above is only looking at modules inside the entry bundle. Any other bundle (DLL… and maybe code splits, I would need to double-check that) is not examined.
This is the problem you’ve identified.
The root cause is in
aurelia-loader-webpack
, the solution would be to dig deeper into Webpack’s internals and look at modules into other (e.g. DLL) bundles that have been loaded. As this is all undocumented stuff, it would need a bit of research.@jods4
01-No_splits
demo I opened the prompt fromferngully-aurelia-tools
successfully - the modification I did in theferngully-aurelia-tools
plugin was:Origin.get(compositionContext.viewModel).moduleId
is resolved OK.Origin.get(compositionContext.viewModel).moduleId
resolves toundefined
. The only difference I see is in the build setup - one bundle vs multiple bundles. The vendors bundle, in which isferngully-aurelia-tools
, is build with the DLL plugin. How can this affect your magic forOrigin.get(...).moduleId
you will say.OK, so had to launch it from VS to get the
dist
rebuild. I’ll post more tomorrow.This should work for finding it:
Also do check the aurelia-webpack wiki since here I see 2 issues:
moduleId
- webpack related