bridgetown icon indicating copy to clipboard operation
bridgetown copied to clipboard

docs: Add a mention for how to glob image files (frontend bundler)

Open matiaskorhonen opened this issue 2 years ago • 3 comments

Currently it seems that if you want to use webpack_path with an image in frontend/images/, it's not possible if the same image isn't used in a JS or CSS file (e.g. import "../images/file.png" in frontend/javascript/index.js).

This limitation isn't mentioned anywhere in the docs, as far as I can see.

Bridgetown Version: 0.21.5

To Reproduce

  1. Create a fresh Bridgetown site
  2. Add an image to frontend/images/
  3. Try to use that file on a liquid page (e.g. <link rel="icon" type="image/png" href="{% webpack_path images/favicon.png %}" />)

Current behavior

An opaque error is printed to the logs:

[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.
[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.
[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.
[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.
[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.
[Bridgetown]            Webpack: There was an error parsing your images/favicon.png file. Please check your images/favicon.png file for any errors.

And the emitted mark-up is:

<link rel="icon" type="image/png" href="MISSING_WEBPACK_MANIFEST_FILE" />

Expected behavior

I would expect, based on the documentation, to be able to use any image from frontend/ with the #webpack_path helper to take advantage of file hashes etc…

Screenshots

Computing environment (please complete the following information):

  • OS: macOS Big Sur
  • Browser: any browser
  • Browser Version —
  • Ruby Version: 2.6.6

Additional context

matiaskorhonen avatar Oct 25 '21 07:10 matiaskorhonen

I managed to fix this for my site by adding copy-webpack-plugin:

// webpack.config.js
const path = require("path");
const { merge } = require('webpack-merge')
const CopyPlugin = require("copy-webpack-plugin");

let config = require("./config/webpack.defaults.js")

const customConfig = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "frontend/**/*.{png,svg,jpg,jpeg,gif}"),
          to: "../images/[name].[contenthash][ext]"
        },
      ],
    }),
  ],
};

config = merge(config, customConfig)

module.exports = config

matiaskorhonen avatar Oct 25 '21 08:10 matiaskorhonen

Thanks @matiaskorhonen, I think your CopyPlugin idea is pretty cool. I've also seen code that you can add to your entrypoint that loops over files and requires them, thus adding them to the manifest. Wonder which approach is better…

jaredcwhite avatar Oct 29 '21 15:10 jaredcwhite

Updating this issue to cover adding a mention for how to glob image files in both esbuild and Webpack frontend bundler configs.

jaredcwhite avatar Jan 20 '22 16:01 jaredcwhite

Speaking of the frontend developer, this can also be used with videos too? Not just images.

Thanks for the quick fix @matiaskorhonen, looks like that should work for me as well. I'd always had issues using the frontend bundler with images, only got it work correctly with CSS/SCSS.

SudoVanilla avatar Nov 28 '22 02:11 SudoVanilla

Speaking of the frontend developer, this can also be used with videos too? Not just images.

Yeah, I don't see why not. You'd just need to add mp4 or webm or whatever to the glob pattern…

I used the same setup for both images and data files on the @euruko 2022 conference site: https://github.com/euruko/2022.euruko.org/blob/2496dfb206b5c6835bc82e0d7981a786fb89169e/webpack.config.js#L27-L43

matiaskorhonen avatar Nov 28 '22 08:11 matiaskorhonen

I seem to have issues with this as I work wit esBuild better than Webpack.

I gave esbuild-plugin-copy a try, but keeps resulting in:

copy is not a function

Code:

const build = require("./config/esbuild.defaults.js")
const outputFolder = "output"
const copy = 'esbuild-plugin-copy';

const esbuildOptions = {
    plugins: [
      copy({
        assets: {
          from: ['./frontend/images/*'],
          to: ['./output/images/*',],
        },
      }),
    ],
}

build(outputFolder, esbuildOptions)

SudoVanilla avatar Dec 12 '22 15:12 SudoVanilla

@jaredcwhite id say a copy plugin that writes to a manifest is better. The problem with the manifests that are generated by doing import statements is that the strings get inlined into the final bundle, so you would need to make a separate assets entrypoint that you never use.

Also, ESBuilds asset detection is spotty at best since the asset -> hashed asset requires some workarounds.

https://github.com/evanw/esbuild/issues/2731

KonnorRogers avatar Dec 12 '22 18:12 KonnorRogers