React-Webpack多頁

react- scripts 中的一系列技術棧配置都 在使用create-react-app構建項目時並未開放,須要使用如下命令彈射到應用的頂層以供個性化,不過特別注意,整個過程是不可逆的 ,eject後就能夠看見熟悉的webpack配置目錄config。javascript

npm run eject
複製代碼

webpack 是什麼?歸根到底,webpack 就是一個.js 配置文件,你的架構好或壞 都體如今webpack.config.js這個配置裏。html

webpack配置中最重要也是必選的兩項是入口(Entry)和出口(Output)。入口的做用是告訴webpack從哪裏開始尋找依賴,而且編譯,出口則用來配置編譯後的文件儲存位置和文件名。java

經過觀察發現 entry 處 只配置了一個入口 paths.appIndexJs ,點進去能夠看見指向index.js。react

entry: [
  // Include an alternative client for WebpackDevServer. A client's job is to
  // connect to WebpackDevServer by a socket and get notified about changes.
  // When you save a file, the client will either apply hot updates (in case
  // of CSS changes), or refresh the page (in case of JS changes). When you
  // make a syntax error, this client will display a syntax error overlay.
  // Note: instead of the default WebpackDevServer client, we use a custom one
  // to bring better experience for Create React App users. You can replace
  // the line below with these two lines if you prefer the stock client:
  // require.resolve('webpack-dev-server/client') + '?/',
  // require.resolve('webpack/hot/dev-server'),
  isEnvDevelopment &&
    require.resolve('react-dev-utils/webpackHotDevClient'),
  // Finally, this is your app's code:
  paths.appIndexJs,
  // We include the app code last so that if there is a runtime error during
  // initialization, it doesn't blow up the WebpackDevServer client, and
  // changing JS code would still trigger a refresh.
].filter(Boolean),
複製代碼
webpack官方文檔有介紹 入口起點(entry points)的多種書寫形式以下:
entry: './path/to/my/entry/file.js'  //單個入口(簡寫)語法
entry: {
    main: './path/to/my/entry/file.js'  //對象語法
}
 entry: {  //多頁面應用程序
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
 }
複製代碼

這裏能夠看出將 單個入口 改寫爲 對象語法 的多頁面應用程序就能夠達到多入口的目的。webpack

工程化 能夠用到 globby 的幫助 搜尋 src 目錄下的多頁面應用:web

// 引入 globby 模塊
const globby = require('globby');
// 入口文件路徑
const entriesPath = globby.sync([resolveApp('src') + '/*/index.tsx']);
複製代碼

經過遍歷 globby 得到的目錄數組 得到 多頁面 路徑入口文件:npm

function getEntries(){
  const entries = {};
  const files = paths.entriesPath;
  files.forEach(filePath => {
    let tmpArr = filePath.split('/');
    let name = tmpArr[tmpArr.length - 2];
    entries[name] = [
      filePath,
    ];
    isEnvDevelopment && entries[name].push(require.resolve('react-dev-utils/webpackHotDevClient')); 
    //這份代碼是由react官方的create-react-app提供的熱構建插件
  });
  return entries;
}
複製代碼
入口 boundle 如何插入對應的 html 中?

咱們一般須要這個插件HtmlWebpackPlugin自動處理,目前代碼是這樣:數組

new HtmlWebpackPlugin(
  Object.assign(
    {},
    {
      inject: true,
      template: paths.appHtml,
    },
    isEnvProduction
      ? {
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeRedundantAttributes: true,
            useShortDoctype: true,
            removeEmptyAttributes: true,
            removeStyleLinkTypeAttributes: true,
            keepClosingSlash: true,
            minifyJS: true,
            minifyCSS: true,
            minifyURLs: true,
          },
        }
      : undefined
  )
),
複製代碼

配置 HtmlWebpackPlugin 插件, 指定入口生成對應的 html 文件,有多少個頁面就須要 new 多少個 HtmllWebpackPlugin webpack配置多入口後,只是編譯出多個入口的JS,同時入口的HTML文件由HtmlWebpackPlugin生成,也需作配置。 chunks,指明哪些 webpack入口的JS會被注入到這個HTML頁面。若是不配置,則將全部entry的JS文件都注入HTML。 filename,指明生成的HTML路徑,若是不配置就是build/index.html,須要 配置新的filename,避免與第一個入口的index.html相互覆蓋。bash

咱們已經 經過 globby 的幫助拿到多入口對象 entries,這裏能夠遍歷處理:架構

const htmlPlugin = Object.keys(entries).map(item => {
  return  new HtmlWebpackPlugin(
      Object.assign(
          {},
          {
            inject: true,
            template: paths.appHtml,
            filename: item + '.html',
            chunks: [item]
          },
          isEnvProduction
              ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
              : undefined
      )
  );
});
複製代碼

將 處理完成的 htmlPlugin 放入對應的 plugins,這裏能夠使用擴展運算符( spread ):

plugins: [
  ...htmlPlugin,
  
      如下代碼省略... 
複製代碼

如此能正常的打包出正確的 多頁面應用了,可是開發環境會受到靜態資源名字沒有Hash 而出現白屏,須要將 出口(Output)開發環境靜態資源加上 Hash值:

output: {
  // The build folder.
  path: isEnvProduction ? paths.appBuild : undefined,
  // Add /* filename */ comments to generated require()s in the output.
  pathinfo: isEnvDevelopment,
  // There will be one main bundle, and one file per asynchronous chunk.
  // In development, it does not produce real files.
  filename: isEnvProduction
    ? 'static/js/[name].[contenthash:8].js'
    : isEnvDevelopment && 'static/js/[name].bundle.js',
  // TODO: remove this when upgrading to webpack 5
  futureEmitAssets: true,
  // There are also additional JS chunk files if you use code splitting.
  chunkFilename: isEnvProduction
    ? 'static/js/[name].[contenthash:8].chunk.js'
    : isEnvDevelopment && 'static/js/[name].chunk.js',
    
    如下代碼省略... 
複製代碼

歡迎光臨個人博客交流學習

相關文章
相關標籤/搜索