ç§ã¯ããã«ãŠã§ã¢ãrazzleãµãŒããŒã«è¿œå ããŠããã¡ã€ã«åã«Webpack [hash:8]
ãŸãã¯[contenthash:8]
ãå«ãrazzleã«ãã£ãŠæ§ç¯ããããã¡ã€ã«ãæäŸãããã³ã«ãããæ€åºããããã®æè¯ã®æ¹æ³ã調æ»ããŠããŸããã ç§ãæåã«ããã§ééããŠããåé¡ã®ããã€ãã«ã€ããŠè°è«ããŸããhttps://github.com/jaredpalmer/razzle/pull/1368#issuecomment-664015050
ãäžå€ããšèŠãªãããå®å
šãªãã¡ã€ã«/ã¢ã»ããã®ãªã¹ããçæããŠå
¬éãããã®ã§ããïŒå¿çã«Cache-Control
ããããŒãèšå®ããããïŒãè¿œå ã®å€æãè¡ããªããŠãç°¡åã«äœ¿çšã§ããŸãããã£ã³ã¯.jsonããã³/ãŸãã¯assets.jsonãã¡ã€ã«
泚ïŒé·æéæå¹ã§äžå€ã®ãã£ãã·ã¥å¶åŸ¡å¿çãèšå®ããå Žåã誀æ€ç¥ã«ãããã¡ã€ã«ãäžå€ãšèŠãªããããã©ããïŒãã¡ã€ã«åã®ããã·ã¥ãæ€åºããããã®å¥åregexïŒã«ã€ããŠããããªãçš®é¡ã®ãè¿äŒŒããè¡ããªãããã«ããŸãããã¡ã€ã«ã¯é·æéäžå€ã«ãã£ãã·ã¥ãããŠããããµãŒããŒåŽã®ãã£ãã·ã¥ã®ç¡å¹åã§ã¯ä¿®æ£ã§ããŸãããããã¯ãåé¿ããã®ãéåžžã«é¢åãªåé¡ã«ãªãå¯èœæ§ããããŸãã
çŸåšå ¬éãããŠããjsonãã¡ã€ã«ã䜿çšããããšããã®ãé£ããçç±ã®TL; DRïŒ
chunks.json
ãšassets.json
äž¡æ¹ã䜿çšããå¿
èŠããããŸãã chunks.jsonã«ã¯ãœãŒã¹ããããã¡ã€ã«ãå«ãŸããassets.jsonã«ã¯png / fontsãªã©ã®ãã¡ã€ã«ãå«ãŸããŸããchunks.jsonã«ã¯å«ãŸããŸããã(assets.json).client
ãªããã£ã³ã¯ïŒäŸïŒ "client": { "js": "/static/js/bundle.6fc534aa.js" }
ïŒã®å Žåãassets.jsonã¯ä»ã®ãã¹ãŠã®ã¢ã»ããã空ã®æååïŒäŸïŒ "": { "js": "/static/js/0.cb47cee9.chunk.js" }
ïŒã§ã°ã«ãŒãåããŸãã"client": { "css": ["filename.css"] }
ïŒãassets.jsonã«ãã¡ã€ã«ãã¡ã€ã«ã1ã€ãããªãå Žåã¯ã代ããã«åäžã®æååïŒäŸïŒ "client": { "css": "filename.css" }
ïŒã"json": "/../chunks.json"
ãå«ãŸããŠããŸãããããã¯ããã«ããã¹ãã ãšã¯æããŸããïŒããããã°ãã©ããã¯ããããŸããïŒãããªã¹ããäœæãããšãã«æåã§ãããåãé€ãå¿
èŠããããŸãé·æéæå¹ãªãã£ãã·ã¥ãäžããããšãã§ãããã¡ã€ã«-å¿çããããŒãå¶åŸ¡ããŸããchunks: ["1", "2", "3"]
é
åãchunks.jsonã«è¿œå ããèšç»ã¯ã次ã®ãããªãã¡ã€ã«ã®é
åãå«ãŸããŠããªãããã (chunks.json).client.chunks
ãé€å€ããããã«è¿œå ã®äœæ¥ãè¡ãå¿
èŠããããããããé¢åã§ãã (chunks.json).client.css
ããã³(chunks.json).client.js
ãªã©ãclient
ãã£ã³ã¯ã«ãªããã¡ã€ã«ã¯ã chunks.json
ãã¡ã€ã«ã«ã衚瀺ãããŠããŸãã"client": {/* blah */ }
ïŒã§ã¯ãªããã£ã³ã¯ãåŠçãããšãã«ã chunks.json
ãšassets.json
ã¹ããŒããããã«å€æ§åããããšã§ããçŸåšassets.jsonãšchunks.jsonã䜿çšããŠããŸãããããã¯ç§ããããŸã§å€§ãŸãã«ããªããã°ãªããªãã£ãããšã§ã
ç§ã¯ããŠããŸããïŒ
"chunks": ["1", "2", "3"]
ã"json": "/../chunks.json"
ããã«ãjsonå
ã®ãã¡ã€ã«/ãã£ãŒã«ããé€å€ããããšã¯æå³ãããŠããŸããfunction razzleCacheableFiles() {
// TODO: Add loading the assets.json file to support (png/txt files etc)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST!);
const filesByType = Object.entries(chunks).reduce(
(chunkAcc: any, [, chunk]) => {
const types = Object.entries(chunk as any).reduce(
(typeAcc, [fileType, files]) => {
return {
[fileType]: chunkAcc[fileType]
? [...chunkAcc[fileType], ...(files as string[])]
: files,
};
},
{},
);
return types;
},
{},
);
const files = Object.entries(filesByType).reduce(
(acc: any[], [, files]) => [...acc, ...(files as string[])],
[],
);
return files;
}
const cacheableFiles = razzleCacheableFiles();
// Serve static files located under `process.env.RAZZLE_PUBLIC_DIR`
const assetCaching = {
immutable: {
maxAge: CacheFor.OneMonth,
sMaxAge: CacheFor.OneYear,
},
default: {
maxAge: CacheFor.OneDay,
sMaxAge: CacheFor.OneWeek,
}
};
app.use(
serve(process.env.RAZZLE_PUBLIC_DIR!, {
setHeaders(res, path) {
const filename = path.replace(process.env.RAZZLE_PUBLIC_DIR!, "");
const hasHashInFilename = cacheableFiles.includes(filename);
if (hasHashInFilename) {
const { immutable } = assetCaching;
res.setHeader(
"Cache-Control",
`max-age=${immutable.maxAge},s-maxage=${immutable.sMaxAge},immutable`,
);
return;
}
res.setHeader(
"Cache-Control",
`max-age=${assetCaching.default.maxAge},s-maxage=${asetCaching.default.sMaxAge}`,
);
},
}),
);
çŸåšã®åäœ/䜿çšæ³ã«ã€ããŠã®æ確ã§ç°¡æœãªèª¬æã
ãããè¡ãã«ã¯ããããå€ãã®æ¹æ³ããããŸãããç§ãæãã§ããäž»ãªããšã¯ãrazzleãã«ãã«ãã£ãŠçæããããã¹ãŠã®ãã£ãã·ã¥å¯èœ/äžå€ã¢ã»ããã®é åãããŒãããæ¹æ³ã§ãã çµæã¯æ¬¡ã®ããã«ãªããŸãã
// File: caching.json
// contains all files/assets with a hash in them regardless of what type of file they are.
{
"immutable": [
"/static/js/0.cb47cee9.chunk.js",
"/static/js/0.cb47cee9.chunk.js.map",
"/static/js/0.cb47cee9.chunk.js.LICENSE.txt",
"/static/media/ferris-error.407b714e.png"
],
// I'm not even sure if this is required because I don't think razzle generates any files that don't have hashes in them?
// possibly files copied in from the `public/` directory during build. but I'm not even sure if it'd that'd useful
"standard": []
}
// RAZZLE_CACHING_MANIFEST is probably a silly name but
const cacheableFiles = require(process.env.RAZZLE_CACHING_MANIFEST!);
// Serve static files located under `process.env.RAZZLE_PUBLIC_DIR`
const assetCaching = {
immutable: {
maxAge: CacheFor.OneMonth,
sMaxAge: CacheFor.OneYear,
},
default: {
maxAge: CacheFor.OneDay,
sMaxAge: CacheFor.OneWeek,
}
};
app.use(
serve(process.env.RAZZLE_PUBLIC_DIR!, {
setHeaders(res, path) {
const filename = path.replace(process.env.RAZZLE_PUBLIC_DIR!, "");
const hasHashInFilename = cacheableFiles.immutable.includes(filename);
if (hasHashInFilename) {
const { immutable } = assetCaching;
res.setHeader(
"Cache-Control",
`max-age=${immutable.maxAge},s-maxage=${immutable.sMaxAge},immutable`,
);
return;
}
res.setHeader(
"Cache-Control",
`max-age=${assetCaching.default.maxAge},s-maxage=${asetCaching.default.sMaxAge}`,
);
},
}),
);
ç§ã¯è¯ã解決çãäœã§ããããå®å
šã«ã¯èª¿æ»ããŠããŸããããå®è¡æã«assets.json
ãšchunks.json
ã䜿çšããŠãã®ããã£ãã·ã¥å¯èœãªã¢ã»ãããã®ãªã¹ãããŸãšããããšããåŸããããå®çŸããããã®æäœéã®æåã®æ¹æ³ã¯ããã«ãæã«äœããã®Webpackãã©ã°ã€ã³ã䜿çšããããã2ã€ã®ãã¡ã€ã«ã®äžæŽåãåé¿ããããšã§ãã
ç§ã®ç®çã®ããã«ãç§ã¯ããããæåã«ããããŸã§è¡ã£ãŠããããã«å®è¡æã«ã§ã¯ãªããã©ã°ã€ã³ã䜿çšããŠãããå®çŸããæ¹æ³ãæ€èšãå§ããŸããããããããã©ã«ãã§çŒãä»ããããšã«ã¯å€§ããªäŸ¡å€ããããšæããŸãã ããã·ã¥åããããã¡ã€ã«ã«é·æéã®ãã£ãã·ã¥å¶åŸ¡ãèšå®ã§ããããšããæåã«ããã·ã¥åãããäž»ãªçç±ã§ãããããããããã¹ãŠã®ãã¡ã€ã«ã®ãªã¹ããå ¬éããããšãé©åã§ãããšæãããŸãã
razzleã«ãã£ãŠçæããã³ããã·ã¥ããããã¡ã€ã«ã«å¯ŸããŠãé©åãªé·å¯¿åœã§äžå€ã®ãã£ãã·ã¥å¶åŸ¡å¿çããããŒãèšå®ããããŠãŒã¶ãŒã
chunks.json
ãšassets.json
äžç·ã«å£ããŠãå®è¡æã«ãã¹ãŠã®äžå€/ãã£ãã·ã¥å¯èœãªãã¡ã€ã«ã®ãªã¹ããçæããŸãïŒãšã©ãŒãçºçããããå£ããããããã§ãïŒãrequire(process.env.RAZZLE_CACHING_MANIFEST!)
ã ïŒïŒç§ã¯ãã®å€æŽãè¡ãããã«åãã§æ¯æŽ/è²¢ç®ããããšæããŸãããæ£ããæ¹åã«å°ããã€ã³ããå¿ èŠãªå ŽåããããŸãïŒãã¡ããããããåãå ¥ã/æè¿ãããå€æŽã§ãããã©ããïŒã
ãŸãããã®ãããªãã®ããããšã httpsïŒ/ãå¯èœã§ããã°ã [hash:8]
ïŒãã«ãããã·ã¥ïŒã§ã¯ãªã[contenthash:8]
ã䜿çšããŠããããšã確èªããããã®ãã¹ã/å®å®æ§ãç°¡åã«åŸãããšãã§ããŸãã /github.com/jaredpalmer/razzle/issues/1331
ããã¯äŸ¡å€ã®ããã¢ã€ãã¢ã®ããã§ãã
ãŸããæé©åã«ãããchunkGroupæ§æã§ããå¥ã®åé¡ã«ãé¢é£ããŠããŸãã ãããèšå®ãããŠããå Žåã空ã®æååã¯ãå ±æããããã¬ãŒã ã¯ãŒã¯ããªã©ã«ãªãããã§ãã
next.jsãèŠããšã次ã®ãããªchunkGroupsæ§æã䜿çšãããŠããŸãã
ãããå€æŽãããšãäžäœäºææ§ããªããªããŸãããå®è¡ããå¿ èŠããããŸãã ã¡ãžã£ãŒãªãªãŒã¹ãå¿ èŠãªãããã«å€§ããªå€æŽãè¡ãããŠããŸãã
ããããããã解決ããã³ãŒããèªç±ã«èããŠãã ããð
next.jsãèŠããšã次ã®ãããªchunkGroupsæ§æã䜿çšãããŠããŸãã
ãã£ããããä»ã®ããŒã«/ãã¬ãŒã ã¯ãŒã¯ãããã«ã¢ãããŒããããã©ãã/ã©ã®ããã«ã¢ãããŒããããã¯ããããŸãããããªã³ã¯/äŸã¯ãããŸããïŒ
ãŸããæé©åã«ãããchunkGroupæ§æã§ããå¥ã®åé¡ã«ãé¢é£ããŠããŸã
æªè§£æ±ºã®ã©ãºã«åé¡ïŒ ããå€ãã®ã³ã³ããã¹ããååŸã§ããããã«ãã©ããæå®ããŠããããŸããð
ããã解決ããããã®æœåšçãª1ã€ã®æ¹æ³ã¯ãæ¢åã®chunks.json
ãšassets.json
ã®åœ¢ç¶/ã¹ããŒãããã匷åã«å®çŸ©ããããšã ãšæããŸãã ããããæ
éã«æ€èšããå¿
èŠããããŸãïŒãããŠã¡ãžã£ãŒããŒãžã§ã³ã®ãã³ãããããŸãïŒããä»ã®ãã¬ãŒã ã¯ãŒã¯ãªã©ãåé¡ãã©ã®ããã«è§£æ±ºãããã®äŸãããå Žåã¯ãåæ§ã®æ¹åã«åŸãããšãçã«ããªã£ãŠãããããããŸãã
ãããŠ
https://github.com/vercel/next.js/blob/canary/packages/next/build/webpack-config.ts#L378
圌ãããããã§ã¹ããã©ã®ããã«è¡ããã«ã€ããŠã¯ããããããŸããã
ä»ããhttps://github.com/jaredpalmer/razzle/issues/1377ãèŠãŠãæ°ããäŸãè¿œå ããŸãã:)
@fivethreeoç¹ã«ãã®åé¡ã«ãã以äžæéãè²»ããããšãã§ããŸããã§ããð ãç§ã¯ééããªãv4ãã¬ãªãªãŒã¹ãè©ŠããŠã¿ãããšã«æéãè²»ãããŸãã æºåãã§ããŠãããšãèãã®å Žåã¯ãä»åŸæ°æ¥ã§è©ŠããŠã¿ãããšæããŸãã
èå³ããããã©ããã¯ããããŸããããçŸåšåãçµãã§ããããšãããã§å ¬éã
ç§ã¯v4ã«ããªãç±å¿ã§ããããã¯ãç¹ã«typescriptã®å Žåãããã§èšå®ããå¿ èŠã®ããããã©ã°ã€ã³ããªãŒããŒã©ã€ããã§ããã ãå€ãåé€ã§ããããšãæå³ããããã§ãã
ãã£ãã·ã¥å¯èœãªã¢ã»ããã®ãã®ã¯ããã«ãã
çŸåšããã¹ãŠã®ãã¡ã€ã«ã§contenthashã䜿çšãããŠããŸãã ç§ãèšãã³ããŒããããã¡ã€ã«ã¯ãç§ãã¡ããã³ãã©ãŒãæã£ãŠãããšãã¯æªãç¿æ £ã§ãã
ããã³ãã©ãŒãããå Žåãã³ããŒããããã¡ã€ã«ã¯æªãç¿æ £ã§ãããšã¯ã©ãããæå³ãããããŸããã
çŸåšã®åäœã¯ãrazzleãããžã§ã¯ãã®æäžäœã®public/
ãã©ã«ããŒã«ãã¡ã€ã«ãé
眮ããå Žåã§ãã
build/
public/
robots.txt
manifest.json
package.json
razzle build
å®è¡ãããšãéçã¢ã»ããã«å¯Ÿå¿ããŸãã
build/
public/
robots.txt
manifest.json
static/
...
public/
robots.txt
manifest.json
package.json
ç§ã¯ã³ããŒãã-ã«ããŠãã«ãæã«ã圌ãã¯å¥ã ã«ãã£ãã·ã¥å¶åŸ¡ãé©çšããããã®ãå ·äœçã¿ãŒã²ããè¡šããŠããããã«ããã¹ãŠã®è³ç£ã®ãªã¹ããç¶æããããã«æãŸãããããããªãèããŠããŸããã
ããã«å¯Ÿããè°è«ïŒç§ãèããããšãã§ããïŒã¯ããŠãŒã¶ãŒããã«ãäžã«razzleãã³ããŒã€ã³ãããã¡ã€ã«ãšã razzle build
å€ã«æåã§æ¿å
¥ããããã¡ã€ã«ãåºå¥ããå¿
èŠããªããããããªããšããããšã ãšæããŸãã
publicã«ã¯robots.txtãšfavicon.icoã®ã¿ãå«ããå¿ èŠããããããã·ã¥ã«ãã£ãŠããŒãžã§ã³ç®¡çãããããšã¯ãªããšæããŸãã
ãã以å€ã¯webpackã«ãã³ãã«ããå¿ èŠããããŸãã ãã倧ããªãã¡ãã³ã³ã¯ãã³ãã«ããå¿ èŠããããŸãã
ãã¶ããããããããã©ã«ãã®create-react-app
ãšã®ããã©ã°ã¢ã³ããã¬ã€ãäºææ§ãç¶æãããå Žåã§ããã¢ããªãããã§ã¹ããšããã€ãã®ã¢ã€ã³ã³ãããã«ååšããããšãèæ
®ãã䟡å€ããããããããŸããã
manifest.json
/ manifest.webmanifest
ãã«ãããã·ã¥ãå«ããã¹ãã§ã¯ãªãçç±ãããããšã倧ãã«èŠããŠããŸããããã¯ããã³ãã©ãŒã«ããåŠçããããªãé »ç¹ã«é€å€ãããçç±ã®1ã€ã§ãã ç§ã¯ééã£ãŠãã/èŠããŠããªããããããŸããããããããPWAãšãªãã©ã€ã³ã¢ãŒãã«é¢ä¿ããŠããŸã
é åçãªãµã³ãã«ãããžã§ã¯ãã®ãããããPWAïŒããã³/ãŸãã¯ãµãŒãã¹ã¯ãŒã«ãŒïŒãµããŒããå®è£ ããŠããŸããïŒ
é¢é£æ§ã¯äœããããããŸããããcreate-react-appã䜿çšãããšãã«éå»ã«public/
ãã©ã«ããŒã«çœ®ããä»ã®ããã€ãã®ãã®ã¯ãWebãµã€ãã«é¢é£ããããŠã³ããŒãå¯èœãªãã¡ã€ã«ã§ãããæ°žç¶çãªURLãå¿
èŠã§ãã ã¡ãŒã«ãªã©ãéä¿¡ãããšãã«ãªã³ã¯ã§ããPDFããã¥ã¡ã³ããæã£ãŠãããããªãã®ã§ãð€·
Webãããã§ã¹ãããã³ãã©ãŒã«åé¢ããå¿ èŠãããå Žå/çç±/ææã®äŸãæ¢ããŠã¿ãŸãã
ãã®æçš¿ã«ã¯ã httpsïŒ //github.com/w3c/manifest/issues/446#issuecomment-351368893ã«ãªã³ã¯ããŠããã³ã¡ã³ãããã
ã¯ããããŠã³ããŒãå¯èœãªãã¡ã€ã«ã¯ããã«è¡ãå¿ èŠããããŸãã ããŒããã§ããããã®ãã¡ã€ã«ãassets.jsonã«è¿œå ããã«ã¯ã©ãããã°ããã§ããïŒ äœãæ¡ã¯ïŒ ðwebpackã«ããããèŠã€ããŠãã®ãŸãŸãã³ãã«ãããå¿ èŠããããŸããïŒ Assets.jsonãå€æŽããã®ã¯ããã¯ã®ããã§ãã
PWAã®äŸã¯ãªããšæããŸãã ãã ããäžè²«ããååãå¿ èŠãªå Žåã ããã¯webpackã§åŠçããå¿ èŠããããŸãã
ã¢ã»ãããã©ã°ã€ã³ããããã§ã¹ããã©ã°ã€ã³ã«çœ®ãæããŠãåºåã調æŽã§ããããã«ããŸãã
æ°ããã¢ã»ãããè¿œå ããŸãã-ãã¹ãŠã®ãã¡ã€ã«ãå«ããããã§ã¹ãhttps://github.com/jaredpalmer/razzle/commit/1c6e9169e9d8eee256d0f118f8a88da8de85989fæ¹åã«é¢ããææ¡ã¯ãããŸããïŒ
ä»ã«ããªã¢ããªãªãŒã¹ããŸãã:)
ãããã§ã¹ããã©ã°ã€ã³ãå®éã«ç¶æãããŠããªãããã§ãã æåã¯ç§ãã¡èªèº«ã§è¡ãããšã§ãã ããããç§ã¯çŸåšèª°ãç¥ããŸããããïŒå€åïŒç§ããããã§ããwebpackã®äººã ã§ãã
ã«ããªã¢ãã©ã³ãã«è¿œå ãããŸããã ä»ã®ãšããããã¯ã®ãããªãã®ã§ãã ããããããã¯æ©èœããæ¹åã§ããã¹ã¿ãŒãã§ãã
ããã€ãæ€èšããåŸããããã³ã¢ã«è¿œå ããŸããã
ãããããããç§ãæãã€ããã³ãŒãã§ãïŒ
new ManifestPlugin({
fileName: path.join(paths.appBuild, 'assets.json'),
writeToFileEmit: true,
generate: (seed, files) => {
const entrypoints = new Set();
const noChunkFiles = new Set();
const longTermCacheFiles = new Set();
files.forEach(file => {
if (file.isChunk) {
const groups = (
(file.chunk || {})._groups || []
).forEach(group => entrypoints.add(group));
} else {
noChunkFiles.add(file);
}
if (!webpackOptions.fileLoaderExclude.some(re=>re.test(file.path))) {
let fileHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.fileLoaderOutputName == 'function' ?
webpackOptions.fileLoaderOutputName(file) : webpackOptions.fileLoaderOutputName);
if (fileHasHash) longTermCacheFiles.add(file);
} else if (webpackOptions.urlLoaderTest.some(re=>re.test(file.path))) {
let urlHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.urlLoaderOutputName == 'function' ?
webpackOptions.urlLoaderOutputName(file) : webpackOptions.urlLoaderOutputName);
if (urlHasHash) longTermCacheFiles.add(file);
} else if (webpackOptions.cssTest.some(re=>re.test(file.path))) {
let cssHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.cssOutputFilename == 'function' ?
webpackOptions.cssOutputFilename(file) : webpackOptions.cssOutputFilename);
if (cssHasHash) longTermCacheFiles.add(file);
} else if (webpackOptions.jsTest.some(re=>re.test(file.path))) {
let jsHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.jsOutputFilename == 'function' ?
webpackOptions.jsOutputFilename(file) : webpackOptions.jsOutputFilename);
if (jsHasHash) longTermCacheFiles.add(file);
}
});
const entries = [...entrypoints];
const entryArrayManifest = entries.reduce((acc, entry) => {
const name =
(entry.options || {}).name ||
(entry.runtimeChunk || {}).name ||
entry.id;
const allFiles = []
.concat(
...(entry.chunks || []).map(chunk =>
chunk.files.map(path => config.output.publicPath + path)
)
)
.filter(Boolean);
const filesByType = allFiles.reduce((types, file) => {
const fileType = file.slice(file.lastIndexOf('.') + 1);
types[fileType] = types[fileType] || [];
types[fileType].push(file);
return types;
}, {});
const chunkIds = [].concat(
...(entry.chunks || []).map(chunk => chunk.ids)
);
return name
? {
...acc,
[name]: { ...filesByType, chunks: chunkIds },
}
: acc;
}, seed);
entryArrayManifest['noentry'] = [...noChunkFiles]
.map(file => file.path)
.reduce((types, file) => {
const fileType = file.slice(file.lastIndexOf('.') + 1);
types[fileType] = types[fileType] || [];
types[fileType].push(file);
return types;
}, {});
entryArrayManifest['cacheable'] = [...longTermCacheFiles]
.map(file => file.path);
return entryArrayManifest;
},
})
ããããç§ã¯è³ç£ã«ã€ããŠå€ããåŠã³ãŸãã;ïŒ
ç³ãèš³ãããŸãããããã°ããã®éããã§å€ãã®æéãéããããšãã§ããŸããã§ããããããã¯ãããã«èŠããŸãã ç§ã®ãã®ãææ°ã®å®å®ããã©ãºã«ããŒãžã§ã³ã«ã¢ããã°ã¬ãŒãããã«ã¹ã¿ã ãã©ã°ã€ã³ãšããŠããªãã®ææ¡ãè©ŠããŠã¿ãŠãã ããã
ããã¯ããªãè¯ãããã«èŠããŸãããç§ã¯ããã«ã€ããŠå°ãæ··ä¹±ããŠããŸãïŒ
let fileHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.fileLoaderOutputName == 'function'
? webpackOptions.fileLoaderOutputName(file)
: webpackOptions.fileLoaderOutputName);
if (fileHasHash) longTermCacheFiles.add(file);
webpackOptions.fileLoaderOutputName
ãšã¯ã©ãããæå³ã§ããïŒ ç§ã«ãšã£ãŠãããã¯åžžã«æªå®çŸ©ã®ããã§ãã
ã©ãºã«ã«ããªã¢ã®ã¿
ãã¡ããšãç§ã¯ä»ãç§ã®ãããžã§ã¯ãã®ãã©ã³ããã«ããªã¢ãã©ã³ãã§åäœãããããšã§ããããã®é²æ©ãéããŸããã çŸæç¹ã§ã¯ãç§ã®åé¡ã¯äž»ã«å åŒããã±ãŒãžãèªèããããã«babelããŒããŒãæ§æããããšã«é¢ä¿ããŠããããã§ãã ãã«ãã¯ã§ããŸãããå®è¡ããããšãããšãã¢ãžã¥ãŒã«ãèŠã€ãããŸããããšããåé¡ãçºçããŸãã
ããã¯ããããããŸãé¢çœããªãã䟿å©ã§ã¯ãããŸãããã次ã®ããã«ãªããŸãã
https://github.com/bootleg-rust/sites/pull/2/files
ã¡ã¢ãªããç§ã¯ããšããšhttps://github.com/jaredpalmer/razzle/issues/664ããèšå®ãåããŸãã
/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/lib-ssr-runtime sync:2
var e = new Error("Cannot find module '" + req + "'");
^
Error: Cannot find module 'undefined'
at require (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/lib-ssr-runtime sync:2:10)
at razzleCacheableFiles (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/lib-ssr-runtime/server.tsx:106:18)
at createKoaApp (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/lib-ssr-runtime/server.tsx:61:26)
at Module.call (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/src/server.tsx:42:13)
at a (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/webpack/bootstrap:19:22)
at Object.call (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/server.js:1:31123)
at __webpack_require__ (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/webpack/bootstrap:19:22)
at /Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/webpack:/webpack/bootstrap:83:10
at Object.<anonymous> (/Users/jstableford/Desktop/@bootleg-rust/sites/packages/web-rust-lang/build/server.js:1:935)
https://github.com/jaredpalmer/razzle/issues/1459
NODE_PATH = ../ãªã©ãèšå®ããŸã
ãã¶ããããã§ããã€ãå€æŽããå¿ èŠããããŸãã
https://github.com/jaredpalmer/razzle/blob/canary/packages/razzle/config/modules.js
ããŠãå°ãæãäžããŠã¿ããšãåé¡ã®åå ã¯å®éã«ã¯process.env.RAZZLE_CHUNKS_MANIFEST
ãå®çŸ©ãããŠããªãããšã«æ°ã¥ããŸããð
ã
ç§ãããã䜿çšããŠããã®ã¯ããã£ãã·ã¥å¯èœãªã¢ã»ãããæ€åºããããšã ãã ã£ãã®ã§ããªã³ã¯ããæ°ããManifestPlugin
ä»ããå®è¡ããŠçœ®ãæããããšãã§ããã¯ãã§ãðã
OKïŒ
ç§ã¯èªåã®ãããžã§ã¯ãã§ã«ã¹ã¿ã ãã©ã°ã€ã³ãäœæããŸããããåœé¢ã¯ç§ã®ãŠãŒã¹ã±ãŒã¹ã§ååã«æ©èœããããã§ãã ããªããæãã€ããã³ãŒãã¯ããããåºçºç¹ãšããŠéåžžã«åœ¹ã«ç«ã¡ãŸããã
ç§ã¯ãããããªãå€æŽããŸããããåèãŸã§ã«ãããã¯Array.prototype.every()
代ããã«Array.prototype.some()
Array.prototype.every()
䜿çšããããããã¹ãŠãfile-loader
ã«ãã£ãŠåŠçããããšèŠãªããããšããåé¡ããããšæããŸãïŒ !webpackOptions.fileLoaderExclude.every(re=>re.test(file.path))
ããã§å ±æãããšäŸ¿å©ãªå ŽåïŒ
function modifyWebpackConfig({
env: { target, dev },
webpackConfig,
webpackObject,
options: { pluginOptions, razzleOptions, webpackOptions },
paths,
}) {
// TODO: allow passing in extra file categorizers with `pluginOptions`
const fileCategorizers = [
{
test: webpackOptions.urlLoaderTest,
outputName: webpackOptions.urlLoaderOutputName,
},
{
test: webpackOptions.cssTest,
outputName: webpackOptions.cssOutputFilename,
},
{
test: webpackOptions.jsTest,
outputName: webpackOptions.jsOutputFilename,
},
{
exclude: webpackOptions.fileLoaderExclude,
outputName: webpackOptions.fileLoaderOutputName,
},
];
const fileName = path.join(paths.appBuild, "cacheable-assets.json");
const assetPlugin = new WebpackManifestPlugin({
fileName,
writeToFileEmit: true,
generate: (seed, files) => {
const notHashedFiles = new Set();
const hashedFiles = new Set();
const setFileAs = (file, { containsHash }) => {
if (containsHash) {
hashedFiles.add(file);
} else {
notHashedFiles.add(file);
}
};
files.forEach((file) => {
if (file.name.startsWith("..")) {
// Files that start with ".." will live outside of the public/
// folder and therefore can't/shouldn't be accessed.
return;
}
const fileCategorized = fileCategorizers.some(
({ test, exclude, outputName }) => {
const passesTest =
test != null ? fileMatchesAnyRegexp(file, test) : true;
const passesExclude =
exclude != null ? !fileMatchesAnyRegexp(file, exclude) : true;
const fileMatches =
passesTest &&
passesExclude &&
fileMatchesTemplate(file.path, outputName);
if (fileMatches) {
const containsHash = webpackLoaderOutputContainsHash(
outputName,
file,
);
setFileAs(file, { containsHash });
}
return fileMatches;
},
);
if (!fileCategorized) {
// TODO: allow "strict" vs "lazy" mode here where we can only use
// regex on the filename to guess if a file contains a hash in it.
setFileAs(file, { containsHash: false });
}
});
const mutable = [...notHashedFiles].map((file) => file.path);
const immutable = [...hashedFiles].map((file) => file.path);
return {
mutable,
immutable,
};
},
});
if (target === "web") {
webpackConfig.plugins.push(assetPlugin);
}
if (target === "node") {
// NOTE: adding multiple DefinePlugin's causes issues
// so we have to find and edit the existing one.
const definePlugin = webpackConfig.plugins.find(
(p) => p.constructor.name === "DefinePlugin",
);
definePlugin.definitions[
"process.env.RAZZLE_PLUGIN_CACHEABLE_ASSETS"
] = JSON.stringify(fileName);
}
return webpackConfig;
}
const cacheableAssetsPlugin = {
modifyWebpackConfig,
};
ãŸãã¯ããã¡ãã§ç¢ºèªã§ããŸãhttps://github.com/bootleg-rust/sites/pull/2/files#diff -59ee436c0396a1f925f067b7e7cbcdee354003236a279e0a87cf8831c7f587e3
ãããããããããšãã ç§ã¯ãŸã æ°ãããã©ã°ã€ã³ããã¯ã«æ £ããŠããŸããç§ã¯ããã奜ãã§ãðïŒ
ç§ããŸã 解決ã§ããŠããªãå¯äžã®äž»ãªåé¡ã¯ã razzle start
ã䜿çšããŠéçºã¢ãŒãã§å®è¡ããŠãããšãã«äœããã®çç±ã§scss
ãã©ã°ã€ã³/ããŒããŒãæ©èœããªãããšã ãšæããŸãrazzle start
ãã razzle build
ããã¹ãŠå®è¡ãããšããã¹ãŠåé¡ãªãããã§ãã
ãããäœã§ãããã«ã€ããŠäœãèãã¯ãããŸããïŒ ãããšãããããå¥ã®githubã®åé¡ã«çœ®ã䟡å€ããããŸããïŒ
ãŸããã«ã¹ã¿ã ãã¹ã«ãmodifyPathsã䜿çšããŠãæ§æã§ããããã«ããŸãã
ã©ã®ããã«åäœããŸãããïŒ
æ°ããåé¡ãããããŸãã.. :)
æ°ã«ããªãã§ãã ãããsassããŒããŒãæ©èœããªãããšã¯razzleã«ç¹æã®ãã®ã§ã¯ãããŸããã§ããã ããŒãžã§ã³ã®äžäžèŽãšé¢ä¿ããããã react-scripts
ããŒãžã§ã³ããã³/ãŸãã¯depsãæã¡äžããŠããå
åŒããã±ãŒãžã«å«ãŸããŠããã¹ããŒãªãŒããã¯ãšé¢ä¿ããããŸãã
è³ç£åŠçã®ããã®ããã¯ãè¿œå ããçµäºããŸãð
å€éšãã©ã°ã€ã³ãè¿œå ããããã§ãã ç§ã¯ãŸã ã¯ã©ã€ã¢ã³ã/ãµãŒããŒ/ãµãŒããŒã¬ã¹ã®ããã«ãããä¿®æ£ããå¿ èŠããããŸãã ã«ããªã¢ã§ãã®ããã®ã¢ã€ãã¢ã¯ãããŸããïŒ å°ãç«ã¡åŸçã
ããªããä»äœ¿ã£ãŠããããã¯ã¯ããã§ãã
å€éšãã©ã°ã€ã³ãè¿œå ããããã§ãã ç§ã¯ãŸã ã¯ã©ã€ã¢ã³ã/ãµãŒããŒ/ãµãŒããŒã¬ã¹ã®ããã«ãããä¿®æ£ããå¿ èŠããããŸãã ã«ããªã¢ã§ãã®ããã®ã¢ã€ãã¢ã¯ãããŸããïŒ å°ãç«ã¡åŸçã
ãã¹ãŠã®node_modules
ãããã©ã«ãã§build/server.js
ã«ãã³ãã«ããããšã¯ãïŒäž»ã«ãµãŒããŒäžã§ïŒéåžžã«äŸ¿å©ã§ããããšãééããªãããããŸããã node_modules
ãã©ã«ããŒããããã¯ã·ã§ã³Dockerã€ã¡ãŒãžããå®å
šã«é€å€ã§ããã®ã¯ããšãŠãçŽ æŽãããããšã®ããã§ãã
ãã€ãã£ã/ãã©ãããã©ãŒã åºæã®äŸåé¢ä¿ã§ã©ã®ããã«æ©èœãããã䜿çš/ãã¹ãããå¿ èŠã¯ãªããšèšã£ãŠããŸããïŒimagemagickã®ãããªãã®ã«åé¡ããããšæããŠããŸãïŒ
ç§ãäœæãããexternalsããã©ã°ã€ã³ã䜿çšããç§ã®äžè¬çãªæèããã»ã¹ã¯æ¬¡ã®ãšããã§ãã
const externalsPluginOptions = {
// By default the NodeJS process uses the externals function razzle has and relies on `node_modules` to still be available
// after performing a razzle build. Setting this to `true` would mean that all dependencies attempt to get bundled into
// the build/ output unless explicitly specified as an external
resetNodeExternals: false,
// This probably wouldn't actually be required because the browser runtime
// doesn't have externals by default (i'm assuming)
resetWebExternals: true,
webExternals: [
// add externals for the web runtime here
],
nodeExternals: [
// add externals for the node runtime here
],
};
ãã®ããã®ãé©åãªãæ§æAPIã決å®ããåã«æ£çŽã«èšããšïŒç¹ã«ãããã©ãºã«ã³ã¢ã«ãªãå ŽåïŒã externals
ã®webpackããã¥ã¡ã³ããããå°ã詳ããèªãå¿
èŠããããŸããå€éšã®ããŸããŸãªãŠãŒã¹ã±ãŒã¹ð
ã
çŸæç¹ã§ã¯ãå®éã«ã¯å€éšã空ã«ãªã»ããããããã«ã®ã¿äœ¿çšããŠãããããå®è¡æã«node_modulesã«äŸåããªãç°¡åã«ããŒã¿ãã«ãªã¢ããªã«ãã¹ãŠããã³ãã«ã§ããŸã
æãåèã«ãªãã³ã¡ã³ã
ä»ã«ããªã¢ããªãªãŒã¹ããŸãã:)