He estado investigando la mejor manera de agregar un middleware a mi servidor razzle para detectar cada vez que sirve un archivo creado por razzle que incluye un paquete web [hash:8]
o [contenthash:8]
en el nombre del archivo. Primero discutí algunos de los problemas con los que me estoy encontrando aquí https://github.com/jaredpalmer/razzle/pull/1368#issuecomment -664015050
Me gustaría que Razzle genere y exponga la lista de archivos / activos seguros para ser considerados "inmutables" (con el propósito de establecer Cache-Control
encabezados en las respuestas) de una manera que sea fácil de consumir sin una transformación adicional del archivos chunks.json y / o assets.json
NOTA: al configurar respuestas de control de caché inmutables y de larga duración, quiero evitar hacer cualquier tipo de "aproximación" sobre si un archivo puede considerarse inmutable (también conocido como regex para detectar un hash en el nombre del archivo) porque un falso positivo puede conducir a un archivo que se almacena en caché de forma inmutable durante mucho tiempo y no podría solucionarse mediante una invalidación de la caché del lado del servidor, lo que puede ser un problema muy doloroso de solucionar.
TL; DR de por qué es difícil intentar usar los archivos json actualmente expuestos:
chunks.json
y assets.json
. chunks.json incluye archivos sourcemap y assets.json tiene archivos como png / fonts, etc. que chunks.json no tiene.(assets.json).client
(por ejemplo: "client": { "js": "/static/js/bundle.6fc534aa.js" }
), assets.json agrupe todos los demás activos bajo una cadena vacía (por ejemplo: "": { "js": "/static/js/0.cb47cee9.chunk.js" }
)."client": { "css": ["filename.css"] }
), si solo hay un archivo de archivo presente en assets.json, en su lugar será solo el una sola cadena (por ejemplo: "client": { "css": "filename.css" }
)."json": "/../chunks.json"
que no es algo que creo que debería estar allí (no estoy seguro si esto es un error o no) pero tengo que eliminarlo manualmente al hacer la lista de archivos que pueden recibir encabezados de respuesta de control de caché de larga duración.chunks: ["1", "2", "3"]
a chunks.json es algo molesto porque significa que tengo que hacer un trabajo adicional para filtrar el (chunks.json).client.chunks
porque no contiene una matriz de archivos como (chunks.json).client.css
y (chunks.json).client.js
etc.client
ni siquiera aparecían en el archivo chunks.json
. Hice / sugerí el cambio para cambiarlo y usar el (los) número (s) de fragmento como clave porque al menos aparecen en el archivo. La desventaja de esto es que ahora chunks.json
y assets.json
más diversos en su esquema cuando se trata de fragmentos que no son el fragmento principal con nombre ( "client": {/* blah */ }
).Actualmente usando assets.json y chunks.json, esto es lo que he tenido que hacer aproximadamente hasta ahora
No tengo:
"chunks": ["1", "2", "3"]
y "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}`,
);
},
}),
);
Una descripción clara y concisa de cuál es el comportamiento / uso actual.
Probablemente haya muchas formas de hacer esto, pero lo principal que quiero es solo una forma de cargar una matriz de todos los activos en caché / inmutables generados por la compilación de razzle. el resultado podría verse así:
// 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}`,
);
},
}),
);
No he investigado completamente cuál sería una buena solución, pero después de intentar armar esta lista de "activos almacenables en caché" en tiempo de ejecución usando assets.json
y chunks.json
, estoy bastante convencido de que en un Como mínimo, la mejor manera de lograr esto sería en el momento de la compilación con algún tipo de complemento de paquete web y evitar las inconsistencias de esos dos archivos.
Para mis propósitos, probablemente comenzaré inicialmente a buscar cómo lograr esto con un complemento en lugar de en tiempo de ejecución como lo he estado haciendo, pero creo que sería de gran valor tener esto integrado para razzle de forma predeterminada. Ser capaz de establecer un control de caché de larga duración en archivos con hash es en gran parte la razón por la que se obtienen con hash para empezar, por lo que parece apropiado exponer una lista de todos esos archivos.
Cualquier usuario que desee establecer encabezados de respuesta de control de caché inmutables y de larga duración adecuados para los archivos generados y hash por razzle.
chunks.json
y assets.json
(parece propenso a errores y frágil).require(process.env.RAZZLE_CACHING_MANIFEST!)
. ()Estaría dispuesto a ayudar / contribuir para hacer este cambio, pero podría necesitar un poco de un punto en la dirección correcta (y por supuesto si este es un cambio que sería aceptado / bienvenido).
También un pensamiento, tener algo como esto podría facilitar tener algunas pruebas / estabilidad para asegurarse de que las cosas estén usando [contenthash:8]
lugar de [hash:8]
(construir hash) si / cuando pueden https: / /github.com/jaredpalmer/razzle/issues/1331
Parece una idea que vale la pena.
También está conectado a otro problema que es la configuración de chunkGroup en optimización. Porque si eso estuviera configurado, la cadena vacía sería "compartida", "marco", etc.
Si miras next.js, usan una configuración de chunkGroups como esta.
Cuando cambiemos esto, también será incompatible con versiones anteriores, pero debe hacerse. Tengo algunos cambios más importantes que también necesitan un lanzamiento importante.
Pero siéntete libre de crear un código que resuelva esto 😀
Si miras next.js, usan una configuración de chunkGroups como esta.
Oh, genial, no sé si / cómo otras herramientas / marcos se acercan a esto, ¿tienes un enlace / ejemplos?
También está conectado a otro problema que es la configuración de chunkGroup en optimización
¿Un problema de razzle abierto? ¿Podrías señalarme cuál para que pueda tener más contexto?
Creo que una forma potencial de resolver esto es definir con más fuerza la forma / esquema de los chunks.json
y assets.json
. Probablemente debería ser considerado cuidadosamente (y tener un aumento de versión principal) pero si hay ejemplos de cómo otros marcos, etc.han resuelto el problema, podría tener sentido seguir una dirección similar
Y
https://github.com/vercel/next.js/blob/canary/packages/next/build/webpack-config.ts#L378
No estoy seguro de cómo hacen el manifiesto.
Eche un vistazo a https://github.com/jaredpalmer/razzle/issues/1377 ahora, se agregó un nuevo ejemplo :)
@fivethreeo No he podido dedicar más tiempo a este tema específicamente 😅, definitivamente intentaré pasar algo de tiempo probando la versión 4. Si cree que está listo, espero intentar probarlo en los próximos días.
No estoy seguro de si es de mucho interés, pero he hecho público lo que estoy trabajando ahora aquí .
Estoy bastante interesado en la versión 4 porque espero que signifique que puedo eliminar tantas modificaciones de "complementos" que tenga que configurar aquí , especialmente para el mecanografiado.
El tema de los activos almacenables en caché está aquí .
Todos los archivos usan contenthash ahora. Los archivos copiados diría que es una mala práctica cuando tenemos un paquete.
No estoy seguro de entender lo que quiere decir con "Los archivos copiados, diría que es una mala práctica cuando tenemos un paquete".
Actualmente, el comportamiento es que si coloca algún archivo en la carpeta de nivel superior public/
en su proyecto razzle.
build/
public/
robots.txt
manifest.json
package.json
Se adaptan a los activos estáticos cuando razzle build
build/
public/
robots.txt
manifest.json
static/
...
public/
robots.txt
manifest.json
package.json
Estaba pensando que sería conveniente mantener una lista de todos los activos que se copiaron durante la compilación para que sean específicamente aptos para el destino por separado para aplicar el control de caché.
Creo que el argumento en contra (en el que puedo pensar) sería que podría no ser necesario que el usuario distinga entre los archivos que razzle ha copiado durante la compilación y los que podrían haberse colocado manualmente allí fuera de razzle build
Creo que public solo debe contener robots.txt y favicon.ico y no serán versionados por hashes.
Todo lo demás debería estar incluido en webpack. Se deben agrupar los favicons más grandes.
Tal vez, pero incluso si desea mantener la compatibilidad "plug and play" con un create-react-app
predeterminado, podría valer la pena considerar que el manifiesto de la aplicación y algunos iconos también estarán presentes allí .
Recuerdo vagamente que hay razones por las que manifest.json
/ manifest.webmanifest
no debería contener un hash de compilación, que es una de las razones por las que a menudo se excluye del procesamiento por parte del paquete. Puede que me equivoque o no lo recuerde, pero posiblemente tenga algo que ver con las PWA y el modo fuera de línea
¿Alguno de los proyectos de ejemplo de razzle implementa el soporte de PWA (y / o trabajador de servicio)?
Quizás menos relevante, pero algunas otras cosas que puse en la carpeta public/
en el pasado al usar create-react-app son archivos descargables relacionados con el sitio web, pero donde se requieren URL persistentes. Como tener un documento pdf al que se puede vincular al enviar correos electrónicos, etc. 🤷
Intentando buscar ejemplos de si / por qué / cuándo los webmanifests deberían estar separados del empaquetado:
Hay un comentario en esa publicación que enlaza con https://github.com/w3c/manifest/issues/446#issuecomment -351368893
Sí, los archivos descargables deberían ir allí. Hm, pero ¿cómo agregamos esos archivos a assets.json? ¿Algunas ideas? 😀 ¿Deberíamos hacer que el paquete web los encuentre y los agrupe como están? Modificar assets.json parece un truco.
No creo que haya un ejemplo de PWA. Pero si necesitan un nombre coherente. Eso debe ser manejado por webpack.
Reemplazaré el complemento de activos con el complemento de manifiesto para que podamos adaptar la salida.
Se agregó un nuevo manifiesto de activos con todos los archivos https://github.com/jaredpalmer/razzle/commit/1c6e9169e9d8eee256d0f118f8a88da8de85989f ¿ Alguna sugerencia sobre mejoras?
Hizo un lanzamiento canario ahora :)
Veo que el complemento de manifiesto no se mantiene realmente. Lo mejor sería hacer las nuestras. Pero actualmente no conozco a nadie más que a mí oa la gente del paquete web que pueda hacer eso.
Agregado a la rama canary ahora. Una especie de truco por ahora. Pero funciona y es un comienzo que se puede mejorar.
Después de considerarlo un poco, no agregaré esto al núcleo.
Pero aquí está el código que se me ocurrió:
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;
},
})
Pero aprendí mucho sobre activos;)
Lo siento, no he podido pasar mucho tiempo con esto en un tiempo, pero se ve bien. Echando un vistazo ahora a actualizar mis cosas a la última versión estable de razzle y probar su sugerencia como un complemento personalizado.
Se ve bastante bien, pero estoy un poco confundido acerca de esto:
let fileHasHash = /\[(build|content)?hash/.test(
typeof webpackOptions.fileLoaderOutputName == 'function'
? webpackOptions.fileLoaderOutputName(file)
: webpackOptions.fileLoaderOutputName);
if (fileHasHash) longTermCacheFiles.add(file);
¿Qué se supone que sea webpackOptions.fileLoaderOutputName
? para mí siempre parece indefinido.
Solo en razzle canary
Aseado, he hecho algunos progresos ahora con la obtención de una rama en mi trabajo de proyecto en la rama canario. No funciona del todo, en este momento mis problemas parecen tener que ver principalmente con la configuración del cargador de babel para reconocer paquetes hermanos. Puedo compilar pero luego obtengo problemas de "no puedo encontrar el módulo" cuando intento ejecutarlo.
Esto probablemente no sea demasiado interesante / útil, pero:
https://github.com/bootleg-rust/sites/pull/2/files
de la memoria originalmente tomé prestada la configuración de 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
y establezca NODE_PATH = .. / o algo
Quizás deberíamos cambiar algunas cosas aquí:
https://github.com/jaredpalmer/razzle/blob/canary/packages/razzle/config/modules.js
Ok, profundizando un poco en él, me acabo de dar cuenta de que el problema en realidad es que process.env.RAZZLE_CHUNKS_MANIFEST
no se define 😅.
Lo único para lo que lo estaba usando era para detectar qué activos se podían almacenar en caché, así que parece que debería poder darle la nueva configuración ManifestPlugin
que vinculó ahora para reemplazarla 🎉.
¡OK!
Hice un complemento personalizado en mi proyecto que parece funcionar lo suficientemente bien para mi caso de uso por el momento. El código que se le ocurrió fue muy útil teniendo eso como punto de partida.
Lo cambié un poco, pero para su información, creo que hay un problema en el que cree que todo lo procesa file-loader
porque usa Array.prototype.every()
lugar de Array.prototype.some()
: !webpackOptions.fileLoaderExclude.every(re=>re.test(file.path))
En caso de que sea útil compartir aquí:
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,
};
O puede verlo aquí https://github.com/bootleg-rust/sites/pull/2/files#diff -59ee436c0396a1f925f067b7e7cbcdee354003236a279e0a87cf8831c7f587e3
Ah, sí, gracias. Todavía me estoy acostumbrando a los nuevos ganchos de complementos, ¡me gusta 🎉!
Creo que el único problema principal que sigo teniendo y que no he podido resolver es que, por alguna razón, el complemento / cargador scss
no funciona cuando se ejecuta en modo de desarrollo usando razzle start
pero si hago un razzle build
completo, todo parece estar bien.
¿Alguna idea de lo que podría ser? ¿O vale la pena poner esto en un problema de github diferente en alguna parte?
También use modifiedPaths para rutas personalizadas también para que se pueda componer.
¿No funciona cómo?
Puede ser un problema nuevo .. :)
No importa, el cargador sass que no funcionaba no era algo específico con el alboroto. algo que ver con una falta de coincidencia de versión o algo con la versión de react-scripts
y / o el libro de cuentos que tenía en un paquete hermano que estaba levantando deps.
Ganchos agregados para manejo de activos, cierre 😀
Veo que agregaste un complemento externo. Todavía necesito arreglar eso para cliente / servidor / sin servidor. ¿Tienes alguna idea para eso en canario? Un poco atascado.
Los ganchos que usas ahora.
Veo que agregaste un complemento externo. Todavía necesito arreglar eso para cliente / servidor / sin servidor. ¿Tienes alguna idea para eso en canario? Un poco atascado.
Definitivamente me pareció muy conveniente (principalmente en el servidor) agrupar por defecto todos los node_modules
en build/server.js
. Ser capaz de excluir la carpeta node_modules
completo de las imágenes de la ventana acoplable de producción me parece muy agradable.
Habiendo dicho eso, no he tenido la necesidad de usar / probar cómo funciona con dependencias nativas / específicas de la plataforma (tengo la sensación de que imagemagick tendría problemas)
Mi proceso de pensamiento general con el complemento "externos" que hice es:
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
],
};
Para ser honesto, antes de decidirme por una API de configuración "adecuada" para esto (particularmente si iba a estar en el núcleo de razzle) probablemente tendría que leer los documentos del paquete web por externals
con un poco más de profundidad en el diferentes casos de uso para externos 😅.
Por el momento, solo lo estoy usando para restablecer los externos para que estén vacíos, de modo que todo se incluya en una aplicación fácilmente portátil que no se basa en node_modules en tiempo de ejecución.
Comentario más útil
Hizo un lanzamiento canario ahora :)