Ich habe nach dem besten Weg gesucht, meinem Razzle-Server eine Middleware hinzuzufügen, um zu erkennen, wann immer eine von Razzle erstellte Datei bereitgestellt wird, deren Dateiname ein Webpack [hash:8]
oder [contenthash:8]
. Ich habe zuerst einige der Probleme besprochen, auf die ich hier stoße: https://github.com/jaredpalmer/razzle/pull/1368#issuecomment -664015050
Ich möchte, dass Razzle die Liste der Dateien / Assets, die sicher sind, als "unveränderlich" (zum Festlegen von Cache-Control
-Header in Antworten) auf eine Weise generiert und verfügbar macht, die ohne zusätzliche Transformation der einfach zu konsumieren ist Dateien chunks.json und / oder assets.json
HINWEIS: Wenn Sie langlebige und unveränderliche Cache-Steuerungsantworten festlegen, möchte ich keine "Annäherung" daran vornehmen, ob eine Datei als unveränderlich angesehen werden kann (AKA-Regex, um einen Hash im Dateinamen zu erkennen), da ein falsches Positiv dazu führen kann Eine Datei wird lange Zeit unveränderlich zwischengespeichert und kann nicht durch eine serverseitige Cache-Ungültigmachung behoben werden. Dies kann ein sehr schmerzhaftes Problem sein.
TL; DR, warum es schwierig ist, die aktuell exponierten JSON-Dateien zu verwenden:
chunks.json
als auch assets.json
. chunks.json enthält Sourcemap-Dateien und Assets.json enthält Dateien wie PNG / Fonts usw., die chunks.json nicht enthält.(assets.json).client
(z. B. "client": { "js": "/static/js/bundle.6fc534aa.js" }
) enthalten ist, assets.json alle anderen Assets unter einer leeren Zeichenfolge gruppiert (z. B. "": { "js": "/static/js/0.cb47cee9.chunk.js" }
)."client": { "css": ["filename.css"] }
). Wenn in assets.json nur eine Dateidatei vorhanden ist, handelt es sich stattdessen nur um die einzelne Zeichenfolge (z. B. "client": { "css": "filename.css" }
)."json": "/../chunks.json"
was meiner Meinung nach nicht enthalten sein sollte (ich bin mir nicht sicher, ob dies ein Fehler ist oder nicht), aber ich muss dies manuell entfernen, wenn ich die Liste von mache Dateien, denen langlebige Cache-Control-Antwortheader zugewiesen werden können.chunks: ["1", "2", "3"]
-Array hinzuzufügen, ist etwas ärgerlich, da ich zusätzliche Arbeit leisten muss, um die (chunks.json).client.chunks
herauszufiltern, da sie kein Array von Dateien wie enthält (chunks.json).client.css
und (chunks.json).client.js
etc.client
waren, nicht einmal in der Datei chunks.json
angezeigt. Ich habe die Änderung vorgenommen / vorgeschlagen, um sie so zu ändern, dass die Blocknummer (n) als Schlüssel verwendet werden, da sie dann zumindest in der Datei angezeigt werden. Der Nachteil davon ist, dass sich jetzt chunks.json
und assets.json
in ihrem Schema weiter unterscheiden, wenn es um Chunks geht, die nicht der primär benannte Chunk sind ( "client": {/* blah */ }
).Derzeit benutze ich die Datei resources.json und chunks.json, was ich bisher ungefähr tun musste
Ich habe nicht:
"chunks": ["1", "2", "3"]
und "json": "/../chunks.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}`,
);
},
}),
);
Eine klare und präzise Beschreibung des aktuellen Verhaltens / der aktuellen Verwendung.
Es gibt wahrscheinlich viele Möglichkeiten, dies zu tun, aber das Wichtigste, was ich möchte, ist nur eine Möglichkeit, ein Array aller zwischengespeicherten / unveränderlichen Assets zu laden, die durch Razzle Build generiert wurden. Das Ergebnis könnte ungefähr so aussehen:
// 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}`,
);
},
}),
);
Ich habe nicht vollständig untersucht, was eine gute Lösung wäre, aber nachdem ich versucht habe, diese Liste der "zwischenspeicherbaren Assets" zur Laufzeit mit den assets.json
und chunks.json
bin ich ziemlich überzeugt, dass bei a Der beste Weg, dies zu erreichen, wäre mindestens die Erstellung mit einer Art Webpack-Plugin und die Umgehung der Inkonsistenzen dieser beiden Dateien.
Für meine Zwecke werde ich wahrscheinlich zunächst untersuchen, wie dies mit einem Plugin und nicht wie bisher zur Laufzeit erreicht werden kann, aber ich denke, es wäre von erheblichem Wert, wenn dieses Back-In standardmäßig zum Blenden gebracht würde. Die Möglichkeit, eine langlebige Cache-Steuerung für gehashte Dateien festzulegen, ist vor allem der Grund, warum sie zunächst gehasht werden. Daher erscheint es angemessen, eine Liste all dieser Dateien verfügbar zu machen.
Alle Benutzer, die geeignete langlebige und unveränderliche Cache-Control-Antwortheader für Dateien festlegen möchten, die von razzle generiert und gehasht wurden.
chunks.json
und assets.json
(scheint fehleranfällig und fragil zu sein).require(process.env.RAZZLE_CACHING_MANIFEST!)
. ()Ich wäre bereit zu helfen / dazu beizutragen, diese Änderung vorzunehmen, aber ich brauche möglicherweise einen Punkt in die richtige Richtung (und natürlich, ob dies eine Änderung ist, die akzeptiert / begrüßt wird oder nicht).
Auch ein Gedanke, so etwas zu haben, könnte es einfacher machen, einige Tests / Stabilität zu haben, um sicherzustellen, dass die Dinge [contenthash:8]
anstelle von [hash:8]
(Build-Hash) verwenden, wenn / wann sie https: / können. /github.com/jaredpalmer/razzle/issues/1331
Dies scheint eine lohnende Idee zu sein.
Es ist auch mit einem anderen Problem verbunden, nämlich der Konfiguration der ChunkGroup bei der Optimierung. Denn wenn das eingerichtet wäre, wäre die leere Zeichenfolge "geteilt", "Framework" usw.
Wenn Sie sich next.js ansehen, verwenden sie eine solche chunkGroups-Konfiguration.
Wenn wir dies ändern, wird es auch abwärtskompatibel sein, aber es muss getan werden. Ich habe noch einige große Änderungen im Gange, die auch eine größere Veröffentlichung erfordern.
Sie können sich aber gerne einen Code einfallen lassen, der dieses Problem löst 😀
Wenn Sie sich next.js ansehen, verwenden sie eine solche chunkGroups-Konfiguration.
Oh cool, ich bin mir nicht sicher, ob / wie andere Tools / Frameworks dies angehen. Haben Sie einen Link / Beispiele?
Es ist auch mit einem anderen Problem verbunden, nämlich der Konfiguration der ChunkGroup bei der Optimierung
Ein offenes Razzle-Thema? Könntest du mir zeigen, auf welche, damit ich mehr Kontext bekomme?
Ich denke, dass eine Möglichkeit, dies zu lösen, darin besteht, die Form / das Schema der vorhandenen chunks.json
und assets.json
stärker zu definieren. Müsste wahrscheinlich sorgfältig überlegt werden (und eine größere Version haben), aber wenn es Beispiele dafür gibt, wie andere Frameworks usw. das Problem gelöst haben, ist es möglicherweise sinnvoll, einer ähnlichen Richtung zu folgen
Und
https://github.com/vercel/next.js/blob/canary/packages/next/build/webpack-config.ts#L378
Ich bin mir nicht sicher, wie sie das Manifest machen.
Schauen Sie sich jetzt https://github.com/jaredpalmer/razzle/issues/1377 an und fügen Sie ein neues Beispiel hinzu :)
@fivethreeo Ich habe es nicht geschafft, mehr Zeit speziell mit diesem Thema zu verbringen. Ich werde auf jeden Fall versuchen, etwas Zeit damit zu verbringen, die v4-Vorabversion auszuprobieren. Wenn Sie denken, dass es dafür bereit ist, werde ich es hoffentlich in den nächsten Tagen ausprobieren.
Ich bin mir nicht sicher, ob es von großem Interesse ist, aber ich habe das, woran ich gerade arbeite, hier öffentlich gemacht.
Ich bin gespannt , hübsch für v4 , weil es hoffentlich bedeutet , dass ich so viele der „Plug -in “ Überschreibungen entfernen kann ich Set Dinge hier , vor allem für Typoskript.
Das zwischenspeicherbare Asset-Zeug ist hier .
Alle Dateien verwenden jetzt Contenthash. Die kopierten Dateien, die ich sagen würde, sind eine schlechte Praxis, wenn wir einen Bundler haben.
Ich bin mir nicht sicher, ob ich verstehe, was Sie unter "Die kopierten Dateien, die ich sagen würde, sind eine schlechte Praxis, wenn wir einen Bundler haben" verstehen.
Derzeit ist das Verhalten so, dass, wenn Sie Dateien in den Ordner public/
der obersten Ebene in Ihrem Razzle-Projekt legen.
build/
public/
robots.txt
manifest.json
package.json
Sie werden in die statischen Assets kopiert, wenn Sie razzle build
build/
public/
robots.txt
manifest.json
static/
...
public/
robots.txt
manifest.json
package.json
Ich dachte, es wäre wünschenswert, eine Liste aller Assets zu führen, die während des Builds kopiert wurden, damit sie speziell für die Anwendung der Cache-Steuerung separat ausgerichtet werden können.
Ich denke, das Argument dagegen (das ich mir vorstellen kann) wäre, dass der Benutzer möglicherweise nicht zwischen Dateien unterscheiden muss, die Razzle während des Builds kopiert hat, und solchen, die möglicherweise manuell außerhalb von razzle build
eingefügt wurden
Ich denke, public sollte nur robots.txt und favicon.ico enthalten und sie werden nicht durch Hashes versioniert.
Alles andere sollte per Webpack gebündelt werden. Alle größeren Favoriten sollten gebündelt werden.
Vielleicht, aber selbst wenn Sie die "Plug and Play" -Kompatibilität mit einem Standardwert von create-react-app
beibehalten möchten, sollten Sie berücksichtigen, dass das App-Manifest und einige Symbole auch dort vorhanden sind .
Ich erinnere mich sehr gut daran, dass es Gründe gibt, warum das manifest.json
/ manifest.webmanifest
keinen Build-Hash enthalten sollte, was einer der Gründe ist, warum es ziemlich oft von der Verarbeitung durch den Bundler ausgeschlossen wird. Ich könnte mich irren / falsch erinnern, aber möglicherweise etwas mit PWAs und dem Offline-Modus zu tun haben
Implementiert eines der Razzle-Beispielprojekte die Unterstützung von PWA (und / oder Servicemitarbeitern)?
Vielleicht weniger relevant, aber einige andere Dinge, die ich in der Vergangenheit bei Verwendung der Create-React-App in den Ordner public/
gestellt habe, sind herunterladbare Dateien, die sich auf die Website beziehen, für die jedoch dauerhafte URLs erforderlich sind. Zum Beispiel ein PDF-Dokument, mit dem beim Versenden von E-Mails usw. verknüpft werden kann
Der Versuch, nach Beispielen zu suchen, ob / warum / wann Webmanifeste vom Bundler getrennt sein sollten:
In diesem Beitrag befindet sich ein Kommentar, der auf https://github.com/w3c/manifest/issues/446#issuecomment -351368893 verweist
Ja, herunterladbare Dateien sollten dorthin gehen. Hm, aber wie fügen wir diese Dateien der Datei resources.json hinzu? Irgendwelche Ideen? 😀Sollen wir das Webpack dazu bringen, sie zu finden und so zu bündeln, wie sie sind? Das Ändern der Datei "resources.json" scheint hackisch.
Ich glaube nicht, dass es ein PWA-Beispiel gibt. Aber wenn sie einen einheitlichen Namen brauchen. Das muss per Webpack erledigt werden.
Ich werde das Assets-Plugin durch das Manifest-Plugin ersetzen, damit wir die Ausgabe anpassen können.
Ein neues Assets-Manifest mit allen Dateien hinzugefügt https://github.com/jaredpalmer/razzle/commit/1c6e9169e9d8eee256d0f118f8a88da8de85989f Verbesserungsvorschläge?
Habe jetzt eine kanarische Veröffentlichung gemacht :)
Ich sehe, dass das Manifest-Plugin nicht wirklich gewartet wird. Das Beste wäre, unser eigenes zu tun. Aber ich kenne derzeit niemanden außer (vielleicht) mir oder den Webpack-Leuten, die das können.
Jetzt zum kanarischen Zweig hinzugefügt. Eine Art Hack für jetzt. Aber es funktioniert und ist ein Anfang, der verbessert werden kann.
Nach einiger Überlegung werde ich dies nicht zum Kern hinzufügen.
Aber hier ist der Code, den ich mir ausgedacht habe:
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;
},
})
Aber ich habe viel über Vermögenswerte gelernt;)
Es tut mir leid, dass ich seit einiger Zeit nicht mehr viel Zeit damit verbringen konnte, aber das sieht ordentlich aus. Schauen Sie sich jetzt an, wie Sie meine Inhalte auf die neueste stabile Razzle-Version aktualisieren und Ihren Vorschlag als benutzerdefiniertes Plugin ausprobieren können.
Es sieht ziemlich gut aus, aber ich bin etwas verwirrt darüber:
let fileHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.fileLoaderOutputName == 'function'
? webpackOptions.fileLoaderOutputName(file)
: webpackOptions.fileLoaderOutputName);
if (fileHasHash) longTermCacheFiles.add(file);
Was soll webpackOptions.fileLoaderOutputName
sein? für mich scheint es immer nur undefiniert zu sein.
Nur in Razzle Canary
Ordentlich, ich habe jetzt einige Fortschritte gemacht, indem ich eine Niederlassung in meinem Projekt dazu gebracht habe, an der kanarischen Niederlassung zu arbeiten. Es funktioniert nicht ganz, im Moment scheinen meine Probleme hauptsächlich damit zu tun zu haben, den Babel Loader so zu konfigurieren, dass er Geschwisterpakete erkennt. Ich kann bauen, bekomme dann aber Probleme mit "Modul kann nicht gefunden werden", wenn ich versuche, es auszuführen.
Dies ist wahrscheinlich nicht zu interessant / nützlich, aber:
https://github.com/bootleg-rust/sites/pull/2/files
Aus dem Speicher habe ich die Konfiguration ursprünglich von https://github.com/jaredpalmer/razzle/issues/664 ausgeliehen
/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
und setze NODE_PATH = .. / oder so
Vielleicht sollten wir hier einige Dinge ändern:
https://github.com/jaredpalmer/razzle/blob/canary/packages/razzle/config/modules.js
Ok, also habe ich mich ein wenig damit beschäftigt und festgestellt, dass das Problem tatsächlich nur dazu führt, dass process.env.RAZZLE_CHUNKS_MANIFEST
nicht mehr definiert wird 😅.
Das einzige, wofür ich es verwendet habe, war zu erkennen, welche Assets zwischengespeichert werden konnten. Es sieht also so aus, als ob ich in der Lage sein sollte, die neue ManifestPlugin
-Konfiguration, die Sie jetzt verlinkt haben, zu testen, um sie zu ersetzen 🎉.
OK!
Ich habe in meinem Projekt ein benutzerdefiniertes Plugin erstellt, das vorerst für meinen Anwendungsfall gut genug zu funktionieren scheint. Der Code, den Sie sich ausgedacht haben, war sehr hilfreich, um diesen als Ausgangspunkt zu verwenden.
Ich habe es ein bisschen geändert, aber zu Ihrer Information, ich denke, es gibt ein Problem damit, bei dem es denkt, dass alles von file-loader
weil dies Array.prototype.every()
anstelle von Array.prototype.some()
: !webpackOptions.fileLoaderExclude.every(re=>re.test(file.path))
Falls es nützlich ist, hier zu teilen:
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,
};
Oder sehen Sie es sich hier an: https://github.com/bootleg-rust/sites/pull/2/files#diff -59ee436c0396a1f925f067b7e7cbcdee354003236a279e0a87cf8831c7f587e3
Ah richtig ja, danke. Ich gewöhne mich immer noch an die neuen Plugin-Hooks, ich mag es 🎉!
Ich denke, das einzige Hauptproblem, das ich immer noch habe und das ich nicht lösen konnte, ist, dass das Plugin / Loader scss
aus irgendeinem Grund nicht funktioniert, wenn es im Entwicklungsmodus mit razzle start
aber wenn ich volle razzle build
mache, scheint alles in Ordnung zu sein.
Irgendwelche Ideen, was es sein könnte? oder lohnt es sich, dies irgendwo auf ein anderes Github-Thema zu setzen?
Verwenden Sie modifyPaths auch für benutzerdefinierte Pfade, damit diese zusammengesetzt werden können.
Funktioniert nicht wie?
Kann eine neue Ausgabe sein .. :)
Egal, der Sass-Lader, der nicht funktionierte, war nichts, was mit Razzle zu tun hatte. Etwas, das mit einer Versionsinkongruenz zu tun hat, oder etwas mit der Version von react-scripts
und / oder Storybook, die ich in einem Geschwisterpaket hatte, das Deps hochzog.
Hooks für Asset-Handling hinzugefügt, Schließen 😀
Ich sehe, Sie haben ein externes Plugin hinzugefügt. Ich muss das noch für Client / Server / Serverless beheben. Hast du irgendwelche Ideen dafür auf Kanarienvogel? Ein bisschen stecken.
Die Haken, die Sie jetzt verwenden, ist.
Ich sehe, Sie haben ein externes Plugin hinzugefügt. Ich muss das noch für Client / Server / Serverless beheben. Hast du irgendwelche Ideen dafür auf Kanarienvogel? Ein bisschen stecken.
Ich habe es definitiv als sehr praktisch empfunden (hauptsächlich auf dem Server), standardmäßig alle node_modules
in build/server.js
zu bündeln. Es scheint einfach super schön zu sein, den Ordner node_modules
vollständig von meinen Docker-Bildern für die Produktion ausschließen zu können.
Trotzdem musste ich nicht verwenden / testen, wie es mit nativen / plattformspezifischen Abhängigkeiten funktioniert (ich habe das Gefühl, dass Dinge wie Imagemagick Probleme haben würden).
Mein allgemeiner Denkprozess mit dem von mir erstellten "externen" Plugin ist:
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
],
};
Um ehrlich zu sein, bevor ich mich für eine "richtige" Konfigurations-API dafür entscheide (insbesondere wenn es sich um einen Razzle-Core handelt), müsste ich wahrscheinlich die Webpack-Dokumente für externals
etwas ausführlicher lesen verschiedene Anwendungsfälle für externe Geräte 😅.
Im Moment benutze ich es wirklich nur, um externe Geräte so zurückzusetzen, dass sie leer sind, damit ich alles in einer leicht portierbaren App bündle, die zur Laufzeit nicht auf node_modules basiert
Hilfreichster Kommentar
Habe jetzt eine kanarische Veröffentlichung gemacht :)