aurelia / webpack-plugin

A plugin for webpack that enables bundling Aurelia applications.
MIT License
90 stars 36 forks source link

Plugin resources not resolved in mono repo #164

Closed searus closed 5 years ago

searus commented 5 years ago

I'm submitting a bug report

Please tell us about your environment:

Current behavior: I created a mono repo using yarn workspaces, with a host app and one plugin. My aim was to find a method to break up a large application into plugins to ease development.

The host app and the plugin were both created with the CLI, then a few small changes made to get going (e.g. changed alias in webpack.config.js to point to hoisted location).

This resulted in an error in the browser: Unable to find module with ID: my-plugin/elements/hello-world.html.

Changing the view to be inline resolved the error and everything worked. Also, placing an import for the view in the host app resolved the error (i.e. import 'my-plugin/elements/hello-world.html';)

My conclusion was the the aurelia-webpack-plugin was not resolving the resources in my-plugin. But, I could be very wrong!

Here's a repro: https://github.com/reyno/aurelia-plugin-repro

NOTE: recreating the entire scenario using the CLI bundler results in a working setup (no error).

jods4 commented 5 years ago

Views that are referenced by convention (i.e. usually a same name file with extension .html along a custom element or viewmodel) are picked up by ConventionDependenciesPlugin.

One instance is included by default by AureliaPlugin and is controlled by options viewsFor and viewsExtensions.

Please note the title has a typo, correct options names are found in the code block. Also doc lies about default value of viewsFor, which is **/!(tslib)*.{ts,js} for better compatibility with npm libs.

Now basically your problem is that only files that match the viewsFor glob are probed for a view by convention. Because my-plugin is outside of your project (i.e. relative path starts with ..), it doesn't match the glob and the view associated with my-plugin/elements/hello-world.js is not considered.

Here are some solutions:

  1. Use @useView instead of conventions in outside code. That's the recommended way for libraries because projects may change the default conventions. Of course in a mono-repo you're in control of everything so that remark doesn't really apply.
  2. Use symbolic links, maybe with yarn workspaces. Honestly it may help but it can also create its own new set of problems.
  3. Just change AureliaPlugin config to include your outside repos!

I tried this:

new AureliaPlugin({ viewsFor: "{src,../my-plugin}/**/*.{ts,js}" })

and it worked for me.

searus commented 5 years ago

@jods4 Thank you for the excellent and detailed answer... everything I need to know!!

Just one more question... you say in point 1 that it's the "recommended way". Is there any documentation on this anywhere as I couldn't find anything? Would it be worth adding this to: https://aurelia.io/docs/plugins/write-new-plugin#structure-of-plugin?

jods4 commented 5 years ago

Good question. I am not sure if/where this can be found in the docs.

To be honest, in practice no plugin does that, which is why I had to change viewsFor default value to include node_modules, otherwise many Aurelia plugins wouldn't work out of the box.

They get away with this because, again in practice, nobody changes the default conventions.

As you can see there's a theory vs practice situation here. At this point I'm not sure if the recommandation really matters as there are so many libs out there that don't follow it.

3cp commented 5 years ago

@searus if you don't have hard requirement on webpack, one thing you can try is to use cli-bundler instead of webpack for the host app. Our plugin scaffolding is using cli-bundler. If your host app is in cli-bundler too, it should find those paired js/html module automatically for you. You might need to adjust host app aurelia.json prepend list if some of the files are not in local node_modules folder.