简体   繁体   中英

Webpack-React with server-side-rendering: linking to css file in server template with hash name

I'm preparing a starter for react from scratch, here is the code: https://github.com/antondc/react-starter

I managed to set up bundling for client and server, with css modules and less, and now I'm with server side rendering. I'm doing that with a js template:

// src/server/views/index.ejs
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>INDEX.EJS</title>
    <link rel="stylesheet" type="text/css" href="assets/index.css">
</head>
<body>
    <div id="app"></div>
    <script src="/assets/bundle.js"></script>
</body>
</html>

As you see, the link to the css file is harcoded there. But in my Webpack configuration I have this file name hashed, because I want to prevent caching from browsers when I update the code on development.

I am wondering how can I link the css file there. Now in the template I have href="assets/index.css , but the css file is in /dist/assets/d47e.css .

It would be great if would be possible to do something like href="assets/*.css , but is not possible, so what is the common approach for a problem like this one?

Thanks!

It depends.

Step 1: Get the current asset name

To get the current name of the generated webpack css/js files, you can use the assets-webpack-plugin . This will (with default config) generate an assets.json file in your output folder with essentially this structure:

{
    "bundle_name": {
        "asset_kind": "/public/path/to/asset"
    }
}

Step 2a: Your html is rendered from a template (pug/jade/what ever)

// in your render code

const assets = require('<webpack-output-folder>/assets.json');

// ...

res.render('template', {
 scripts: [{src: `${WEBPACK_PUBLIC_PATH}/${assets.myEntryPointName.js}` }],
 links: [{href: `${WEBPACK_PUBLIC_PATH}/${assets.myEntryPointName.css}` rel: 'stylesheet' }],
});

// in your template (example for pug)

// ...

each link in links
  link(rel=link.rel href=link.href)

// ...

each script in scripts
  script(src=script.src)

// ...

Step 2b: Your html is static

You need to update the html (using a script) with the information from the asset.json file. This script needs to be run after webpack. Something like

const assets = require('<webpack-output-folder>/assets.json');
const fs = require('fs');

const css = /assets\/[a-z0-9]*\.css/i;
const js = /assets\/[a-z0-9]*\.js/i;

fs.readFile('<yourhtml>.html', (err, data) => {

  // ... (error handling)

  const updatedCss = data.replace(css, assets.myEntryPointName.css);
  const updatedJs = updatedCss.replace(js, assets.myEntryPointName.js);

  fs.writeFile('<yourhtml>.html', updated, (err) => {

    // ... (error handling)

  });

});

您可以使用HTMLWebpackPlugin生成一个HTML文件,该文件将插入您的JS和CSS输出。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM