如何將 css 或 js 文件的時間戳(或哈希)請求參數添加到 NextJS 12 build file.js?ts=[timestamp]


在 NextJs 應用程序中構建後,我需要有機會獲得下一種形式的 js 和 css 文件名:
./path/file.js?ts=[時間戳]
./path/file.css?ts=[時間戳]

我找到了下一個解決方案:

  1. 創建 _document.tsx 並創建繼承自 Document 的類。
class StaticDocument 擴展 Document {
  使成為 () {

    返回 (
      
        
        
          
          
        
      
    )
  }
}
  1. 準備從 Head 擴展的 CustomHead。我在 Head 類的庫中找到了下一個函數並覆蓋了它們:getDynamicChunks、getScripts、getCssLinks:
聲明類型 DocumentFiles = {
  sharedFiles: 只讀字符串[];
  pageFiles: 只讀字符串[];
  allFiles: 只讀字符串[];
};

const timestamp = new Date().getTime();
函數getDynamicChunks(上下文:任意,道具:任意,文件:DocumentFiles){
  const { dynamicImports , assetsPrefix , isDevelopment , devOnlyCacheBusterQueryString , disableOptimizedLoading , crossOrigin , } = context;
  return dynamicImports.map((file: any)=>{
    if (!file.endsWith('.js') || files.allFiles.includes(file)) return null;
    console.log('文件', 文件);
    返回 React.createElement('腳本', {
      異步:!isDevelopment && disableOptimizedLoading,
      defer: !disableOptimizedLoading,
      鍵:文件,
      src: `${assetPrefix}/_next/${encodeURI(file)}${devOnlyCacheBusterQueryString || ('?ts=' + 時間戳)}`,
      隨機數:props.nonce,
      crossOrigin: props.crossOrigin ||跨域
    });
  });
}

函數getScripts(上下文:任意,道具:任意,文件:DocumentFiles){
  讓參考;
  const { assetsPrefix , buildManifest , isDevelopment , devOnlyCacheBusterQueryString , disableOptimizedLoading , crossOrigin , } = context;
  const normalScripts = files.allFiles.filter((file)=>file.endsWith('.js'));
  const lowPriorityScripts = (ref = buildManifest.lowPriorityFiles) == null ? void 0 : ref.filter((file: any)=>file.endsWith('.js'));
  返回 [
    ...正常腳本,
    ...低優先級腳本
  ].map((文件)=>{
    返回 React.createElement('腳本', {
      鍵:文件,
      src: `${assetPrefix}/_next/${encodeURI(file)}${devOnlyCacheBusterQueryString || ('?ts=' + 時間戳)}`,
      隨機數:props.nonce,
      異步:!isDevelopment && disableOptimizedLoading,
      defer: !disableOptimizedLoading,
      crossOrigin: props.crossOrigin ||跨域
    });
  });
}

類 CustomHead 擴展 Head {
  getDynamicChunks(files: DocumentFiles): (JSX.Element | null)[] {
    返回 getDynamicChunks(this.context, this.props, files);
  }
  getScripts(文件:DocumentFiles):JSX.Element[] {
    返回 getScripts(this.context, this.props, files);
  }

  getCssLinks(文件:文檔文件){
    常量 {assetPrefix , devOnlyCacheBusterQueryString , dynamicImports , crossOrigin , optimizeCss , optimizeFonts , } = this.context;
    const cssFiles = files.allFiles.filter((f)=>f.endsWith('.css'));
    const sharedFiles = new Set(files.sharedFiles);
    // 非託管文件是 CSS 文件,將由
    // webpack 運行時 (`mini-css-extract-plugin`)。
    讓 unmangedFiles: any = new Set([]);
    讓 dynamicCssFiles = Array.from(new Set(dynamicImports.filter((file)=>file.endsWith('.css'))));
    if (dynamicCssFiles.length) {
      常量現有 = 新設置(cssFiles);
      dynamicCssFiles = dynamicCssFiles.filter((f)=>!(existing.has(f) || sharedFiles.has(f)));
      unmangedFiles = new Set(dynamicCssFiles);
      cssFiles.push(...dynamicCssFiles);
    }
    讓 cssLinkElements: any[] = [];
    cssFiles.forEach((文件)=>{
      const isSharedFile = sharedFiles.has(file);
      if (!optimizeCss) {
        cssLinkElements.push(React.createElement('link', {
          鍵:`${file}-preload`,
          隨機數:this.props.nonce,
          rel: '預加載',
          href: `${assetPrefix}/_next/${encodeURI(file)}${devOnlyCacheBusterQueryString || ('?ts=' + 時間戳)}`,
          如:'風格',
          crossOrigin: this.props.crossOrigin ||跨域
        }));
      }
      const isUnmanagedFile = unmangedFiles.has(file);
      cssLinkElements.push(/*#__PURE__*/ React.createElement('link', {
        鍵:文件,
        隨機數:this.props.nonce,
        rel: '樣式表',
        href: `${assetPrefix}/_next/${encodeURI(file)}${devOnlyCacheBusterQueryString || ('?ts=' + 時間戳)}`,
        crossOrigin: this.props.crossOrigin ||跨域,
        'data-n-g': isUnmanagedFile ?未定義:isSharedFile? '' : 不明確的,
        'data-n-p': isUnmanagedFile ?未定義:isSharedFile?不明確的 : ''
      }));
    });
    if (process.env.NODE_ENV !== 'development' && optimizeFonts) {
      cssLinkElements = this.makeStylesheetInert(cssLinkElements);
    }
    返回 cssLinkElements.length === 0 ?空:cssLinkElements;
  }
}

我找到了負責創建鏈接的所有行,並推送了帶有時間戳的附加代碼:(‘?ts=’ + timestamp)。

  1. 我對其進行了調試,_documents.tsx 在 npm run dev 上運行。它也在構建過程中運行。但是 _document.tsx 的構建過程包含兩個步驟:a) 構建到 .next 文件夾和 b) _document.js 僅在構建過程中執行。它不會在 npm start 上調用。