6

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!

1
  • any solution yet ? Commented Mar 3, 2019 at 0:03

2 Answers 2

3
+25

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)

  });

});
Sign up to request clarification or add additional context in comments.

Comments

-1

You can use HTMLWebpackPlugin to generate an HTML file that will have your JS and CSS output inserted.

2 Comments

Don't understand why you propose doing that with Webpack, if you read the question you will notice that HTMLWebpackPlugin is not a viable solution.
html webpack plugin is not a good solution for this use case, we generate our template by a function and return the result of it and use it to inject the result of react 's most top components render to string to it to create our file, so it should not be a good solution in this case , if you know any better solution to implement with html webpack plugin , please dont hesitate to share it with us...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.