Razzle: 䞍倉の `Cache-Control`を蚭定しおも安党なすべおのアセットのリストを公開したす

䜜成日 2020幎07月31日  Â·  40コメント  Â·  ゜ヌス: jaredpalmer/razzle

🚀機胜リク゚スト

私はミドルりェアを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ずchunks.jsonは同じ圢匏ではないためwebpackに耇数のチャンクに分割させるため、これはおそらく私に珟れる問題です、すべおのファむルの完党なリストを照合するために異なるアドホック倉換が必芁です/ assets。 いく぀かの違いは次のずおりです。

    • (assets.json).clientないチャンク䟋 "client": { "js": "/static/js/bundle.6fc534aa.js" } の堎合、assets.jsonは他のすべおのアセットを空の文字列䟋 "": { "js": "/static/js/0.cb47cee9.chunk.js" } でグルヌプ化したす。

    • チャンク.jsonグルヌプにファむルが1぀しかない堎合は、アむテムが1぀含たれる配列になりたす䟋 "client": { "css": ["filename.css"] } 。assets.jsonにファむルファむルが1぀しかない堎合は、代わりに単䞀の文字列䟋 "client": { "css": "filename.css" } 。

  • 私のassets.jsonには珟圚"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を䜿甚する

珟圚assets.jsonずchunks.jsonを䜿甚しおいたすが、これは私がこれたで倧たかにしなければならなかったこずです

私はしおいたせん

  • ただassets.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䞀緒に壊しお、実行時にすべおの䞍倉/キャッシュ可胜なファむルのリストを生成したす゚ラヌが発生しやすく壊れやすいようです。
  • ビルド時にキャッシュ可胜なファむルのリストを事前に生成する倖郚プラグむンを䜜成したす。 ベむクむン/安定しおいる必芁があるように芋える機胜に぀いおは、ラズルバヌゞョン間で脆匱である可胜性がありたす
  • これを内郚プラグむンずしおrazzleのデフォルト蚭定に远加し、デフォルトでアクセスする方法を公開したす䟋 require(process.env.RAZZLE_CACHING_MANIFEST!) 。 

远加のコンテキスト

私はこの倉曎を行うために喜んで支揎/貢献したいず思いたすが、正しい方向に少しポむントが必芁な堎合がありたすもちろん、これが受け入れ/歓迎される倉曎であるかどうか。

たた、このようなものがあるず、 https/が可胜であれば、 [hash:8] ビルドハッシュではなく[contenthash:8]を䜿甚しおいるこずを確認するためのテスト/安定性を簡単に埗るこずができたす。 /github.com/jaredpalmer/razzle/issues/1331

discussion enhancement help wanted razzle webpack webpack-config

最も参考になるコメント

今カナリアをリリヌスしたした:)

党おのコメント40件

これは䟡倀のあるアむデアのようです。

たた、最適化におけるchunkGroup構成である別の問題にも関連しおいたす。 それが蚭定されおいる堎合、空の文字列は「共有」、「フレヌムワヌク」などになるためです。

next.jsを芋るず、次のようなchunkGroups構成が䜿甚されおいたす。

これを倉曎するず、䞋䜍互換性もなくなりたすが、実行する必芁がありたす。 メゞャヌリリヌスが必芁な、さらに倧きな倉曎が行われおいたす。

しかし、これを解決するコヌドを自由に考えおください😀

next.jsを芋るず、次のようなchunkGroups構成が䜿甚されおいたす。

かっこいい、他のツヌル/フレヌムワヌクがこれにアプロヌチするかどうか/どのようにアプロヌチするかはわかりたせんが、リンク/䟋はありたすか

たた、最適化におけるchunkGroup構成である別の問題にも関連しおいたす

未解決のラズル問題 より倚くのコンテキストを取埗できるように、どれを指定しおもらえたすか😄

これを解決するための朜圚的な1぀の方法は、既存のchunks.jsonずassets.jsonの圢状/スキヌマをより匷力に定矩するこずだず思いたす。 おそらく慎重に怜蚎する必芁がありたすそしおメゞャヌバヌゞョンのバンプがありたすが、他のフレヌムワヌクなどが問題をどのように解決したかの䟋がある堎合は、同様の方向に埓うこずが理にかなっおいるかもしれたせん

13611370

そしお

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://stackoverflow.com/questions/54145027/what-happens-when-you-add-a-version-hash-to-your-service-worker-file

その投皿には、 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に䟝存しない簡単にポヌタブルなアプリにすべおをバンドルできたす

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡