You’re kind of going against the grain here – I’m not sure why you are hashing some files and not others? What are you trying to accomplish?
Check this out sometime if you’re curious why this is kind of a hassle:
Short summary: rollup doesn’t support this at all, and parcel is just as annoying as webpack. It’s likely not a priority because there aren’t many good reasons to do it. Sage is code split by default, which means that we use a bundler to intelligently and automatically determine what code is needed, and where, and when. You’re kind of throwing a wrench in that by asserting things about how the output should be structured.
Concerns aside, you totally can do this. I’ll give you two options. I would strongly recommend the first approach, but I will admit that the other option is less involved. Keep in mind that the recommended approach is future proof while the other approach may need to be adjusted in the future (if bud.js is still using webpack when webpack 6 releases we’ll likely abandon the tooling we use for css file naming, as webpack will handle it natively).
Recommended approach: two compilers
Sandbox: https://codesandbox.io/p/sandbox/blissful-flower-upg6tm
This is how multiple configurations are handled in Radicle. This is how it looks:
export default async (bud) => {
await bud.make(`app`, async (app) => {
app
.setPath(`@dist`, `./dist/app`)
.entry(`app`, [`app.js`, `app.css`])
.hash()
})
await bud.make(`extra`, async (extra) => {
extra
.setPath(`@dist`, `./dist/extra`)
.entry(`styles`, [`styles.css`])
})
}
Put your existing config as-is into the top bud.make
callback, and then do it again for your extra build step.
You can expect output like this:
╭─ app ./dist/app [8d37991148f3985ead32]
│
├─ entrypoints
│ └─ app
│ ├─ css/app.928106.css 32 bytes
│ └─ js/app.effa7b.js 71 bytes
│
╰─ compiled 3 modules (3 cached) in 411ms
╭─ extra ./dist/extra [ab3179d64128252f67c0]
│
├─ entrypoints
│ └─ styles
│ └─ css/styles.css 333 bytes
│
╰─ compiled 2 modules (2 cached) in 33ms
Added benefit: you can use the --filter
flag to run the builds conditionally. So yarn bud build --filter app
will only build the app
code, which could be very nice if the other code doesn’t need to be built very often.
╭─ app ./dist/app [8d37991148f3985ead32]
│
├─ entrypoints
│ └─ app
│ ├─ css/app.928106.css 32 bytes
│ └─ js/app.effa7b.js 71 bytes
│
╰─ compiled 3 modules (3 cached) in 197ms
You will need to modify the config/assets.php
config file in Sage and adjust your enqueue script (but I imagine you’re already doing that anyway). Again, Radicle can serve as a good reference implementation.
Option 2: Override webpack config
Sandbox: https://codesandbox.io/p/sandbox/determined-kalam-lcgx15
I have a feeling there is a nicer way to express this, but it works:
export default async (bud) => {
bud.entry(`app`, [`app.js`, `app.css`])
bud.entry(`styles`, [`styles.css`])
bud.webpackConfig((config) => {
const findPlugin = (plugin) =>
plugin.constructor.name === `MiniCssExtractPlugin`
const filename = ({ chunk }) =>
chunk.name === `styles` ? `css/styles.css` : bud.relPath(`css/@name.css`)
Object.assign(config.plugins.find(findPlugin).options, {
filename,
})
return config
})
}
This tracks down mini-css-extract-plugin and re-assigns the filename
option. Our new callback returns the css file with no hash if the split chunk in question is named styles
& the standard value otherwise.
In summary
- It is worth interrogating why you are doing this. Clearly you feel hashing is import enough to leave enabled, so why is this asset being treated differently?
- If you feel your reasons are valid you should consider using a multi compiler configuration
- If you go with the
webpackConfig
callback I honestly wouldn’t blame you but you will likely need to adjust it in response to future changes.