Some of my components refer the assets files in a css way:
import styled from 'styled-components';
const Logo = styled.div`
background-image: url('/static/logo.png'),
`
I want to use CDN for all the assets in /statics folder, it is possible to give a version tag( like BUILD_ID) to these files in production?
No clue, anyone has a advice?
Same issue here.
We tried using webpack file loader but seems not working for the current version of next.js.
We also encountered this problem, if the use of file-loader, you can generate a new image, but the node will be reported when compiled:
Error: Cannot find module '../ static / test.png'
So temporarily through githooks to deal with images to modify the problem, allowing add new image, but not allowed to submit modify the image:
.git/hooks/pre-commit
#!/bin/sh
STAGED_IMAGES=$(git diff --cached --name-only --diff-filter=M | grep -E ".(jpg|jpeg|png|gif)$")
if [[ $STAGED_IMAGES ]]; then
echo $STAGED_IMAGES
exit 1
fi
Actually this is pretty easy using the with-universal-configuration example.
File: ./env-config.js
const { version } = require('./package.json')
module.exports = {
'process.env.VERSION': version
}
File: ./pages/index.js
export default () => (
<div>
Build-Version: { process.env.VERSION }
</div>
)
I've created a fork to demonstrate this: HaNdTriX/next.js/tree/with-build-id/examples/with-universal-configuration
If you would like to add this to the examples I can create a standalone example and create a PR.
If this example solves your issue please close it.
Thanks @HaNdTriX 鉂わ笍
@HaNdTriX @timneutkens
Thanks for the suggestion. It seems good for some issues here but not all of them.
For our project, we are working for images hash tags with next.js. It will be better to have the hash for every single image in order to make the browser cache the right one without extra clear work.
So the build version is only working for the release build code but not for the assets stuff as images and css files.
Thanks @HaNdTriX, but I have the same question here, what I want is the production code build all the static files with hash names, such as static/avatar.png -> static/avatar.1898173978.png.
The images may change sometime, we don't to refresh CDN on these files frequently, hash name can avoid this problem.
Could you give me some suggestions?
I thought about something like this:
<style jsx global>{`
body {
background-image: url(static/some-image.png?version=${process.env.VERSION});
}
`}</style>
What you use as an hash is up to you. You can create it yourself in the ./env-config.js.
File: ./build-static.js
const fs = require('fs')
const path = require('path')
const execSync = require('child_process').execSync
const revHash = require('rev-hash')
const srcDir = 'static'
const distDir = 'buildstatic'
const hashData = {}
execSync(`rm -r -f ${distDir}`)
const buildStatic = (src, dist) => {
fs.access(dist, (err) => {
if (err) {
fs.mkdirSync(dist)
}
initBuild(src, dist)
})
}
const initBuild = (src, dist) => {
const paths = fs.readdirSync(src)
paths.forEach((_path) => {
const subSrc = `${src}/${_path}`
const subDist = `${dist}/${_path}`
const stat = fs.statSync(subSrc)
if (stat.isFile()) {
const fileData = fs.readFileSync(subSrc)
const pathObj = path.parse(subSrc)
const hash = revHash(fileData)
const hashDir = pathObj.dir.split(`${srcDir}/`)[1] || ''
const hashKey = `${hashDir}/${pathObj.name}${pathObj.ext}`
const filePath = `${path.parse(subDist).dir}/${pathObj.name}.${hash}${pathObj.ext}`
if (pathObj.ext) {
hashData[hashKey] = hash
fs.writeFileSync(filePath, fileData)
}
} else if (stat.isDirectory()) {
buildStatic(subSrc, subDist)
}
})
fs.writeFileSync('static-hash.json', JSON.stringify(hashData))
}
buildStatic(srcDir, distDir)
run: node build-static.js
File: ./demo.js
import staticHash from 'static-hash'
const isPro = true
const staticRequire = (path) => {
const hash = staticHash[path]
const pathSplit = path.split('.')
const fileName = pathSplit[0]
const fileExt = pathSplit[1]
const filePath = !isPro ? path : `${fileName}.${hash}.${fileExt}`
let staticDir = '/static/'
if (isPro) {
staticDir = 'https://mycdn.com/static/'
}
return `${staticDir}${filePath}`
}
console.log(staticRequire('images/test.png'))
// <img src={staticRequire('images/test.png')} alt="" />
Thanks @taichenglu .
Similar solution here, I decide to add a suffix to static assets (e.g. /static/app_icon.png?v=1).
import qs from 'querystring';
export default (url) => {
if (process.env.BUILD_VERSION) {
const [urlPath, urlQueryString = ''] = url.split('?');
const queryString = qs.parse(urlQueryString);
queryString.v = process.env.BUILD_VERSION;
return `${urlPath}?${qs.stringify(queryString)}`;
}
return url;
}
We use Jenkins to deploy code, the BUILD_VERSION is assigned to Jenkins Job id.
@monopieces
If you do so, each release will update all static files, is not conducive to the client cache.
Most helpful comment
File:
./build-static.jsrun:
node build-static.jsFile:
./demo.js