cli icon indicating copy to clipboard operation
cli copied to clipboard

Including images from the 'static' dir to a CLI generated Webpack project results in duplication in output bundle

Open chrisckc opened this issue 7 years ago • 7 comments
trafficstars

I'm submitting a bug report Here is another issue with the CLI generated webpack config that soon becomes apparent once an app starts to be built.

  • Loader/bundler: Webpack

Current behavior: If you go down the logical steps needed to include an image in your app, ie. add an image inside 'static/images' dir then add the image to your html file like this:

 <img src="../static/images/test.png"

After running 'au build --env prod` and inspecting the contents of the 'dist' dir you will discover that the image has been included twice.

You will see it in it's correct form as a hashed filename such as "904ca927cf30ddc1d7dbbd6593f2f78e.png" as generated by the webpack url-loader plugin.

You will also see it at "images/test.png" as it is also copied over by the CopyWebpackPlugin which results in a second redundant copy.

The offending config entry is here:

...when(production || server, new CopyWebpackPlugin([
      { from: 'static', to: outDir }])),
  • What is the expected behavior? Expected that the image would not included in the output bundle twice.

To fix this issue, the config entry need to be changed to this:

// url-loader handles bundling of png/jpg/gif/svg etc.
// We only need to specify files here that are not referenced in the source files
...when(production || server, new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' }])),

We only need to copy over the favicon as it is not referenced in the source so is not picked up by the webpack rules.

  • What is the motivation / use case for changing the behavior? To provide a better starting experience for new comers to Aurelia or Aurelia / webpack combination.

I am not new to Aurelia but new to webpack, and have so far had to spend quite some time sorting out issues with the webpack config to support various use cases. Simply following the path of using popular libraries such a jQuery or Bootstrap has proven to be problematic as i have detailed in another recent issue.

chrisckc avatar Nov 07 '18 21:11 chrisckc

Questionable

Alexander-Taran avatar Nov 07 '18 22:11 Alexander-Taran

Indeed, however if it is to be left as it is, there needs to be something in the docs that says something along the lines of "When including images that are referenced in the source, do not put them in the 'static' dir, instead either include them next to the source files or in another root directory such as /assets/" along with an explanation as to why this is necessary.

For example we could use a structure like this if an image is to be referenced in welcome.html /src/views/welcome/welcome.ts /src/views/welcome/welcome.html /src/views/welcome/welcome.css /src/views/welcome/test.png

Images shared between views could be placed here: /src/images/

Although images are technically not source files, this would prevent the duplication issue. Or they could be placed in an entirely different directory structure outside of src, next the 'static' dir, for example at /assets/images/

chrisckc avatar Nov 08 '18 11:11 chrisckc

What i am saying above is basically what is described in the Vue.js webpack docs: http://vuejs-templates.github.io/webpack/static.html

Regarding assets referenced i the source:

Since these assets may be inlined/copied/renamed during build, they are essentially part of your source code. This is why it is recommended to place Webpack-processed static assets inside /src, alongside other source files. In fact, you don't even have to put them all in /src/assets: you can organize them based on the module/component using them. For example, you can put each component in its own directory, with its static assets right next to it.

This way we can have both real static assets in the /static/ dir and webpack processed (renamed and hashed etc.) assets in /src/assets/

It would be great if the new/upcoming CLI generated skeleton templates included this kind of example structure with 2 sample images (one smaller than 8k and one larger) referenced to make it clear to new Aurelia/webpack devs how it is supposed to work.

chrisckc avatar Nov 08 '18 12:11 chrisckc

The Vue CLI generated webpack config is much more comprehensive than the one generated by Aurelia CLI. The Vue webpack docs start off with a full description of the project structure: http://vuejs-templates.github.io/webpack/structure.html which makes it easy for newcomers using webpack to understand how it works and where to put things.

Going from zero to a working app is much quicker and easier if the basic structure is already well defined, configured and documented. I think this is one of the reasons that Aurelia struggles to gain traction in the face of it's competition.

chrisckc avatar Nov 08 '18 13:11 chrisckc

are you using some plugin for webpack to process images? if not.. why it touches them and produces hashed versions? If yes.. then it is "src" because they are not static (-:

Alexander-Taran avatar Nov 08 '18 23:11 Alexander-Taran

For documented webpack configs - I'm all in.. https://github.com/aurelia-contrib/aurelia-getting-started/tree/master/config-files/webpack you are welcome to produce some (-:

Alexander-Taran avatar Nov 08 '18 23:11 Alexander-Taran

I am using the section in the standard CLI generated config which uses url-loader for processing images.

I have been a fan of Aurelia ever since it came out and i am just trying to suggest ways to improve the starting experience for newcomers.

The point i am making is that the CLI generated project structure does not indicate to a newcomer where images should go, or rather that they should not go in the 'static' dir. Looking at the skeleton-typescript-webpack project does not help as styles.css is in the static dir, suggesting they go there.

The webpack config in skeleton-typescript-webpack uses this config instead which only copies the favicon:

new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' }
    ]),

It also has styles.css in the 'static' dir, which is actually processed by the css-loader so is really a source file. If a newcomer generates a project with the CLI and then looks at the skeleton repo for some pointers and borrows some of the source and css file as a starting point, they will end up with the css duplicated (doesn't break things but is not good) unless they also borrow that part of the webpack config.

It's reasonable to assume that images would then be placed next to the css file, resulting in those being duplicated as well.

The sooner the CLI and skeletons are aligned the better i think. It would be great if the CLI generated a more complete project structure and webpack config as a good starting point.

I have a repo that i will be updating soon with the results of my efforts to create a nice project structure and webpack config which is documented.

chrisckc avatar Nov 08 '18 23:11 chrisckc