aurelia / webpack-plugin

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

Failed loading required CSS file. Including css from 3rd party library isn't found. [On release candidate 2] #101

Closed rokadias closed 7 years ago

rokadias commented 7 years ago

I'm using aurelia-materialize-bridge and it includes inlineViews which have <require ...> css statements.

Runtime errors occur failing to load css from webpack: Failed loading required CSS file: aurelia-materialize-bridge/slider/slider.css

Switching to using a raw loader for the css files based on this previous issue: https://github.com/aurelia/webpack-plugin/issues/11

  modules: {
    rules: [
      {
        test: /aurelia-materialize-bridge\/dist\/commonjs\/.*\.css$/,
        use: [
          {
            loader: 'raw-loader'
          }
        ]
      },
      {
        test: /\.css?$/,
        exclude: /aurelia-materialize-bridge\/dist\/commonjs\/.*\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          }
        ]
      }
    ...
    ]
  }

This workaround allowed me to run in webpack-dev-server, but I'm stuck with the same error when building the final distributables using webpack.

This was what I could gather when I tried to debug. Basically __webpack_require returns an empty object for moduleId "aurelia-materialize-bridge/slider/slider.css" when aurelia-hot-module-reload expects a string. https://github.com/aurelia/hot-module-reload/blob/master/src/hmr-css-resource.ts#L60

This is why the raw loader fixed it for the hot module load scenario.

I'm submitting a bug report

Please tell us about your environment:

Current behavior: CSS failure described above.

Expected/desired behavior:

Reasons that I have to move to the new webpack loader is hot module updates, looking for improvement on tree-shaking, and will want to use chunking provided by webpack.

jods4 commented 7 years ago

You will find relevant information about which loaders you need for CSS here: https://github.com/aurelia/webpack-plugin/wiki/CSS-doesn't-load

I think there's more than that here. The dev vs prod difference and empty module leads me to believe you're using ExtractTextPlugin to put all your CSS into a separate file for production (which replaces the actual demands with empty modules). I don't think <require> supports that. In that case, we should open an issue in aurelia-templating-resources, where this stuff is implemented.

Lastly, I am unsure how the CSS is included in the build, as @inlineView contents are not parsed by html-require-plugin. I'm not sure if/what we should do about that.

rokadias commented 7 years ago

One of the first things I did was read through the CSS-doesn't-load, and I haven't come across issues with my own scss and css.

I should have clarified that I'm not using ExtractTextPlugin. I'm using webpack-merge and so here's what the difference between dev and prod configuration looks like: https://gist.github.com/rokadias/21e72f08fa1103d8198a0660b49f7b8e

Also as far as aurelia-templating-resources since I'm not using ExtractTextPlugin. I'm not sure if it's applicable. I can add that I'm using aurelia-webpack-plugin 1.1, and only tried moving to the release candidate. I've even tried different versions of webpack webpack@2.2.1 and webpack@2.3.1. Since I ran into this issue between the two versions with webpack-plugin 1.1: https://github.com/webpack/webpack/issues/959

jods4 commented 7 years ago

OK so in light of the additional information above, I read your first post again but I have difficulties understanding everything that's going on.

You use raw-loader, why not css-loader, which would seem more appropriate? (shouldn't make much difference).

This workaround allowed me to run in webpack-dev-server,

What was the code before the work-around? What was the problem and how did it fix it?

run in webpack-dev-server, but I'm stuck with the same error when building the final distributables using webpack.

I've looked at your merged config but I don't see any significant difference between debug and release. webpack-dev-server merely builds the same output as webpack (but keeps it in memory). Did you tell me everything? Can you show what the output in debug mode is, show what the output in release mode is and explain where the difference comes from?

Basically __webpack_require returns an empty object for moduleId "aurelia-materialize-bridge/slider/slider.css"

Any idea why it's empty? Can you please post the output of webpack --display-modules in a gist?

This is why the raw loader fixed it for the hot module load scenario.

I have not understood what raw-loader fixed, nor how exactly. Can you explain it again?

If you have a small repro of the problem I might debug it myself.

rokadias commented 7 years ago

@jods4: I'm able to repro it using the skeleton-typescript-webpack and adding aurelia-materialize-bridge.

I've put in a add-materialize-bridge branch to my fork of skeleton-navigation: https://github.com/rokadias/skeleton-navigation/tree/add-materialize-bridge

The hmr version works: npm start -- webpack.server.hmr

However the following fails:

I haven't gotten any closer to actually figuring out what the underlying issue is. Other than the css resources have "css-resource-plugin!aurelia-materialize-bridge/slider/slider.css" located in front of them in the loader.moduleRegistry which appears to come from aurelia-hot-module-reload.

https://github.com/aurelia/hot-module-reload/blob/master/src/aurelia-hot-module-reload.ts#L227

The moduleId being looked up is still aurelia-materialize-bridge/slider/slider.css without the css-resource-plugin and so that's why I think it can't find it. This is my best guess without fully understanding how everything works.

Thanood commented 7 years ago

Although I have changed the slider component to use a js/html pair instead of an inline view (master branch, not released), I'm very interested in this topic. 😃

This issue might be closely related to https://github.com/aurelia/webpack-plugin/issues/107.

rokadias commented 7 years ago

Any update on this?

Also I don't think the label for this issue is correct with "question".

jods4 commented 7 years ago

Sorry, I assigned this to myself as I meant to have a look but couldn't find the time to. Not having a minimal repro doesn't help unfortunately.

I'll try to have a look. That said, the code you point out, which adds loaders to URL at runtime looks suspicious to me. @niieani how's that supposed to work? Webpack module ids never have a loader prepended at runtime, do they?

jods4 commented 7 years ago

I tried your repo today. As far as I can tell everything worked well (you didn't give specific steps).

  1. Clone https://github.com/rokadias/skeleton-navigation.git
  2. Go to skeleton-esnext-webpack
  3. yarn to restore packages
  4. Webpack 2.3.3 if that matters
  5. yarn run start -- webpack.server.hmr
  6. everything looks ok in the browser, all 3 pages. nothing suspicious in the console.
  7. yarn run start -- webpack.build.development.serve (the watch command you gave me doesn't exist)
  8. again, fine.
  9. yarn run start -- webpack.build.production.serve
  10. again, fine.
rokadias commented 7 years ago

@jods4 Sorry, I thought it was obvious, but sure I'll write up the steps. I mentioned which branch to check out in my comment above. I figured you'd just do a diff from add-materialize-bridge (the branch I mentioned) to master to see the changes that were done and what to look for.

git clone https://github.com/rokadias/skeleton-navigation.git
cd skeleton-navigation
git fetch origin add-materialize-bridge:add-materialize-bridge
git checkout add-materialize-bridge
cd skeleton-typescript-webpack
yarn
yarn run start -- webpack.build.development.serve
jods4 commented 7 years ago

OK I see the problem.

I don't know why it works in HMR mode (would be interesting to check but I don't have time right now), as I expect it not to work.

The first error that I get is that the browser is unable to load slider.css. If you run webpack --display-modules you'll see that the module is indeed nowhere to be found. A quick look at the sources show this for slider.js:

@customElement('md-slider')
@inject(Element)
@inlineView(`
  <template class="slider">
  <require from="./slider.css"></require>
  <ul class="slides">
    <slot></slot>
  </ul>
  </template>
`)
export class MdSlider { /* ... */

So aurelia-materialize-bridge references ./slider.css from a @inlineView. As of aurelia-webpack-plugin version 2.0 RC2, dependencies inside @inlineView are not detected. RC3 has support for that, see #107.

You have 3 solutions:

  1. Use RC3 (not published yet, you'll have to get it from the branch on github and build it). If you do, feedback is welcome as this is a new feature.
  2. Modify slider.js to include moduleName('./slider.css') somewhere. As this is not your code, it's unlikely to be doable, so see 3.
  3. Workaround it with new ModuleDependenciesPlugin({ 'aurelia-materialize-bridge/slider/slider': './slider.css' }).

It is likely that you'll have to do that for a few other components, although a look at --display-modules shows that most of them have their CSS properly bundled.