2017-04-17 8 views
0

반응 서버 쪽 렌더링에 FOUC 문제가 있습니다. 자산을 처리하기위한 별도의 CSS 파일 React Server Side Rendering (CSS Module) FOUC 문제

  • css-modules-require-hook & asset-require-hook를 생성하기위한 구성 요소 스타일
  • extract-text-webpack-plugin

    • CSS Module 거래 : 나는 + ReactRouter + 돌아 오는 여기 주요 기술 스택 내가 필요한 목록에 생각이다 반작용 사용 서버 측

    내 웹팩 설정 :

    module.exports = { 
        entry: [ 
        APP_PATH, 
    ], 
    
        output: { 
        path: BUILD_PATH, 
        filename: 'client.bundle.js', 
        publicPath: '/JdBus/', 
        }, 
    resolve: { 
        extensions: ['.js', '.jsx'], 
    }, 
    module: { 
    rules: [ 
        { 
        test: /\.(js|jsx)$/, 
        exclude: /node_modules/, 
        use: [ 
         'babel-loader', 
        ], 
        }, 
    
        { 
        test: /\.css$/, 
        use: ExtractTextPlugin.extract({ 
         fallback: 'style-loader', 
         use: [ 
         { 
          loader: 'css-loader', 
          options: { 
          modules: true, // 开启CSS Module 
          localIdentName: '[name]__[local]-[hash:base64:5]', 
          }, 
         }, 
         { 
          loader: 'postcss-loader', 
          options: { 
          plugins() { // 这里配置postcss的插件 
           return [autoprefixer]; 
          }, 
          }, 
         }, 
         ], 
        }), 
        }, 
        { // 处理图片 
        test: /\.(png|jpg|gif|webp')$/, 
        // include:path.resolve(__dirname,'/client/assets'), 
        use: [{ 
         loader: 'url-loader', 
         options: { 
         limit: 10000, 
         // 这个是输出的图片文件,跟output一致,生成的是bundleImg目录下的图片文件 
         name: 'bundleImg/[hash:8].[name].[ext]', 
         }, 
        }], 
        }, 
    
        { // 处理文字 
        test: /\.(woff|ttf|svg|eot|woff2)$/, 
        // include:path.resolve(__dirname,'/client/assets'), 
        use: [{ 
         loader: 'url-loader', 
         options: { 
         limit: 10000, 
         name: 'bundleFonts/[hash:8]-[name].[ext]', 
         }, 
        }], 
        }, 
        ], 
    }, 
    plugins: [ 
        new webpack.DefinePlugin({ 
         'process.env': { 
         NODE_ENV: JSON.stringify('production'), 
         WEBPACK: true, 
        }, 
        }), 
        new webpack.optimize.UglifyJsPlugin({ 
        compressor: { 
         warnings: false, 
        }, 
        }), 
        new ExtractTextPlugin('bundle.css'), 
        new webpack.optimize.CommonsChunkPlugin({ 
        name: 'commons', 
        filename: 'commons.js', 
        minChunks: 2, 
        }), 
    }; 
    

    ExtractTextPlugin은 bundle.css에서 모든 CSS 스타일을 생성합니다. 익스프레스 바이

    내 서버 사이드 핸들 :

    function renderFullPage (html, initiaState, env) { 
        // 根据生产和开发环境配置不同的页面 
    if (env === 'development') { 
        return ` 
        <!DOCTYPE html> 
         <html lang="en"> 
         <head> 
         <title>开发测试页面</title> 
         <meta charset="UTF-8"> 
         <meta name="viewport" content="width=device-width, initial- 
         scale=1.0, user-scalable=no"/> 
          <style> 
          body{ 
           margin:0px;  
          } 
          </style> 
         </head> 
    
         <body> 
         <div id="root"></div> 
         <script> 
          window.__INITIAL_STATE__ = ${JSON.stringify(initiaState)}; 
         </script> 
         <script src='/devClient.bundle.js'></script> 
         </body>  
        </html> 
        `; 
        } else if (env === 'production') { 
        return ` 
         <!DOCTYPE html> 
         <html lang="en"> 
         <head> 
         <meta charset="UTF-8"> 
         <title>十二棵橡树</title> 
         <meta name="viewport" content="width=device-width, initial-scale=1.0, 
        user-scalable=no"/> 
         <link rel="stylesheet" type="text/css" href="/JdBus/bundle.css"> 
         <style> 
         body{ 
          margin:0px; 
          scroll:no 
         } 
         </style> 
    
        </head> 
        <body> 
         <div id="root"> 
          ${html} 
         </div> 
         <script> 
         window.__INITIAL_STATE__ = ${JSON.stringify(initiaState)}; 
         </script> 
    
        </body> 
        </html> 
        `; 
        } 
        } 
    module.exports = renderFullPage; 
    

    server.js 어디 프로그램 시작이다 :

    match({ routes: AppRoutes, location: `/jdbus${req.url}` }, (err, redirectLocation, renderProps) => { 
        if (err) { 
         res.status(500).send(err.message); 
        } else if (redirectLocation) { 
         res.redirect(302, redirectLocation.pathname + redirectLocation.search); 
        } else if (renderProps) { 
    
         const store = configureStore({ user: { 
         name: 'ddd', 
         avatar: 'ddd', 
         } }); 
         // console.log(renderProps); 
         const marked = renderToStaticMarkup(
         <Provider store={store}> 
          <RouterContext {...renderProps} /> 
         </Provider> 
        ); 
         const initHtml = renderFullPage(marked, store.getState(), process.env.NODE_ENV); 
         res.status(200).end(initHtml); 
        } else { 
         res.status(404).end('404 not'); 
        } 
        }); 
    

    renderFullPage()veiw.js에서 HTML을 생성하는 기능입니다 :

    // 各种钩子 
        require('babel-polyfill'); 
        require('css-modules-require-hook')({ 
         extensions: ['.css'], 
         generateScopedName: '[name]__[local]-[hash:base64:8]', 
        }); 
    
        require('asset-require-hook')({ 
         extensions: ['jpg', 'png', 'gif', 'webp'], 
         limit: 10000, 
        }); 
        // 处理字体 
        require('asset-require-hook')({ 
         extensions: ['ttf', 'woff', 'svg', 'eot', 'woff2'], 
         limit: 10000, 
        }); 
    
    const app = require('./app'); 
    
    app.listen(PORT,() => { 
        console.log('Node app is running on port:', PORT); 
    
        // 注册全局未捕获异常处理器 
        process.on('uncaughtException', (e) => { 
        console.error(`Caught exception:, ${e.stack}`); 
        }); 
        process.on('unhandledRejection', (reason, p) => { 
        console.error(`Unhandled Rejection at: Promise , ${p}, reason: , ${reason.stack}`); 
        }); 
    }); 
    

    asset-require-hookcss-modules-require-hook은 서버 측에서 처리 할 수없는 자산을 처리합니다.

    FOUC를 제외한 모든 것이 정상입니다. 내 서버 측은 정상적으로 HTML을 생성하지만, 시도 할 때마다 잠시 CSS를 생성하지 않습니다. 다음 enter image description here

  • 답변

    0

    내 webpack.config 파일의 코드 조각입니다 :

    내 스크린 샷입니다. 내 React Server-side Rendering Example에 FOUC 문제가 수정되었습니다. HtmlWebpackHarddiskPlugin에서 alwaysWriteToDisk를 true로 설정하여 HtmlWebpackHarddiskPlugin을 사용하고 있었다고 생각합니다.

    new ExtractTextPlugin({ 
        filename: isDevelopment 
         ? 'assets/styles/main.css' 
         : 'assets/styles/[name].[chunkhash].css', 
    }), 
    
    new HtmlWebpackPlugin({ 
        template: path.resolve(__dirname, 'src/index.html'), 
        minify: isProduction ? {collapseWhitespace: true, collapseInlineTagWhitespace: true} : false, 
        alwaysWriteToDisk: true, 
    }), 
    new HtmlWebpackHarddiskPlugin(), 
    
    +0

    확인해 보겠습니다. Thks – Betamee