Closed zakjan closed 6 years ago
Similar happens when you declare component dependencies via @viewResources
.
Example:
import {Component} from "./component";
PLATFORM.moduleName("./component");
@viewResources(Component)
export class AnotherComponent {
}
If you remove PLATFORM.moduleName("./component"); you'll have "module ... component.html not found"
This happens because moduleName
does more than just add a dependency.
It also prevents Webpack from optimizing your module in ways that break aurelia-loader
, such as: renaming your module, hoisting into another module, tree shaking unused exports and more.
When you ES import
your module Webpack will bundle it into your application, but it will also do all those things, which prevent aurelia-loader
from finding the requested module.
So there's nothing we can do about it.
On the upside, @bigopon is refactoring Aurelia APIs to avoid usage of aurelia-loader
in favor of standard import
(static or dynamic), which means we can progressively get rid of moduleName
and aurelia-webpack-plugin
, eventually.
@jods4 This is understandable with string paths, because there is no real import. But with imported classes, it gets confusing.
What's the general rule when it is necessary to use moduleName
? Is there any automated way how we could check for missing moduleName
and prevent such production-only runtime errors?
The refactoring sounds good, can you point me to the tasks where it is being done, so that we can track the progress?
@zakjan I agree that it's confusing, sadly without refactoring the libraries there's nothing that can be done in a Webpack plugin that would fix this.
Thankfully, passing an object to an API that will later try to fiddle with its aurelia-loader
origin is rather rare. aurelia-dialog
is certainly the most commonly used example.
An automated way to check those would be to have a JS analyzer that has a list of "sensitive" APIs and tracks down the source of their parameters (to the extend that it's possible...) and double-check if there's a matching moduleName
.
It would be a very complex projecta and it would never be perfect.
I hope that you always do acceptance tests of your systems with the same build that you intend to put in production, which should catch those errors as they are not subtle.
I think the refactorings are doing well, if I'm not mistaken a lot have been published already. I'll leave it to @bigopon for the details.
CC @StrahilKazlachev anything to add when it comes to aurelia-dialog
?
For >=aurelia-dialog@1.0.0
when it comes to using a class
for viewModel
you will need to have PLATFORM.moduleName
somewhere. From the issues in dialog I remember that more people preferred adding it in the module of the VM itself - you do need it only once.
I can't guarantee whether it will be this week or not, but we will push out 2.0.0
of the dialog. It will have the same APIs as 1.0.0
, excluding the configuration API(the plugin config one!!). And it requires ^aurelia-templating@1.8.2
.
The commit to drop the usage of Origin
is already pushed.
The only thing left is how to proceed with the default resources - <ux-dialog>
& Co. Will open a PR with proposition this week, I hope.
@jods4 Thanks. Sure we have QA to catch this, but it would be better to catch it earlier in the development process. The current list of sensitive APIs would be:
DialogService.open({viewModel})
<compose view-model.bind="...">
@viewResources
/ @view
/ static $view
Is there anything else?
@zakjan that would be all for now. Router moduleId: () => MyVmClass
is on the list but it will probably take bit more time. Note that @viewResources
relies on Origin
, otherwise you need to use absolute path:
@viewResources(PLATFORM.moduleName('my/absolute/path')) // if MyVm is referenced statically
export class MyVm {
}
I'm submitting a bug report
Library Version: 3.0.0
JSPM OR Webpack AND Version Webpack 4.16.2
Current behavior:
Imported classes passed into Aurelia libraries needs to be imported again with PLATFORM.moduleName for production bundle.
Steps to replicate:
Edit files:
src/app.ts
src/app.html
test/unit/app.spec.ts
src/dialog.ts
src/dialog.html
Run development bundle:
Verify that dialog can be opened.
Run production bundle:
The dialog can't be opened, it throws:
Edit
src/app.ts
, add lines:Therefore now there is both ES native import and Aurelia Webpack Plugin import:
Verify that now the dialog can be opened.
Similar behavior exists when a class reference is used in
@viewResources
or<compose view-model.bind="..."></compose>
.Initially this would affect aurelia-dialog view models only, but now as Aurelia is moving towards more support for class references instead of string paths (https://aurelia.io/blog/2018/06/24/aurelia-release-notes-june-2018/#new-templating-features), this issue becomes more widespread.
Expected/desired behavior:
What is the expected behavior? No need to duplicate file imports for production bundle, native import without PLATFORM.moduleName should be enough.
What is the motivation / use case for changing the behavior? Same behavior of development and production bundle. Limiting PLATFORM.moduleName usages to absolute minimum. If class references are used everywhere instead of string paths, PLATFORM.moduleName shouldn't need to be used at all.