Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use Material-UI framework #14

Closed
Salmon42 opened this issue Mar 5, 2020 · 10 comments
Closed

Unable to use Material-UI framework #14

Salmon42 opened this issue Mar 5, 2020 · 10 comments

Comments

@Salmon42
Copy link

Salmon42 commented Mar 5, 2020

I tried to add React Material-UI to the project template.

This is how it looks in package.json (by simply following the installation routine on material-ui page):

"dependencies": {
    ...
    "@material-ui/core": "^4.9.5",
    "@material-ui/icons": "^4.9.1",
    "@material-ui/styles": "^4.9.0",
    ...
}

And in one of the components simply used material button:

... (ommited other react imports)
import Button from '@material-ui/core/Button';
...
const Component = () => {
    return (
        <Button variant="contained" color="primary">
            Hello World!
        </Button>
    )
}

Somehow, I seem to hit unsolvable error similar to this issue.

jss.esm.js:1712 Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'unsafe-inline' 'nonce-qahp5MvuRSU3PA6LfMc+Vg=='". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

I tried to modify this in webpack.development.js:

new CspHtmlWebpackPlugin({
      'base-uri': ["'self'"],
      'object-src': ["'none'"],
      'script-src': ["'self'"],
      'style-src': ["'self' 'unsafe-inline'"],  // Added unsafe-inline
      'frame-src': ["'none'"],
      'worker-src': ["'none'"],
}),

but it had no effect.

Is there a way to get Material-UI working along with this template? I feel like I'm terribly missing something trivial, but I don't know what else to try. Thanks in advance.

@reZach
Copy link
Owner

reZach commented Mar 6, 2020

Thanks for reporting this, @Salmon42. If the suggestion in the other issue to add 'unsafe-inline' doesn't work, I'd suggest modifying your webpack.config.js in this way.

Before

// loads .css files
{
    test: /\.css$/,
    include: [path.resolve(__dirname, "app/src")],
    use: [
        MiniCssExtractPlugin.loader,
        {
            loader: "css-loader"
        }
    ],
    resolve: {
        extensions: [".css"]
    }
},

After

// loads .css files
{
    test: /\.css$/,
    //include: [path.resolve(__dirname, "app/src")], // removed!
    use: [
        MiniCssExtractPlugin.loader,
        {
            loader: "css-loader"
        }
    ],
    resolve: {
        extensions: [".css"]
    }
},

My thought is that because webpack is only pulling in .css based on the app directory (instead of the node_modules folder, where material ui might have its assets stored), you aren't able to import your css. If this doesn't work, which I hope it would, I would take the question to the material ui team and file an issue/question.

It appears that they are doing some kind of process to import the css into each component. I took a little bit to look at it for you but I don't seem to make sense of it. If my suggestion above doesn't work, I recommend asking the material ui team how the css files are imported, so then we can better understand how to change the webpack/csp settings so material ui works in this template.

FYI this file might also be helpful to look at, but that's just a guess of mine.

@Salmon42
Copy link
Author

Salmon42 commented Mar 6, 2020

I suppose the problem could be related to the idea how material-ui processes CSS styles for each component. If I take a look at the DOM through Inspect Element, we can see the following:

image

This might be incorrect idea, but I have a feeling that these 4 styles (each containing few css declarations for the given component) are ignored because they are not contained in the "compiled" main.css, which is built from all CSS files inside app/src. I tried to search in material-ui whether it's the only way to use default styles of the components, if there is something I could force it to generate the styles into the main.css, but that is way out of my understanding.

Sadly, the only thing I found that "fixes" this issue was by commenting out the whole CSP Webpack Plugin (CspHtmlWebpackPlugin) in webpack.development.js, which I suppose defeats the purpose of safe approach of this template. Without the policy, the multiple style sheets injected by material-ui into element works without any warning, with all styles and component animations.

About the sources you shared, I took a look into them, but I feel that codes only supports writing style sheets in JSS (defining CSS as JS object and then using those methods to bind together with a component). That is (as I understood) moreless a addition to the basic styles and it would not change the way material-ui injects the final styles into DOM.

I'm pretty new to this combination of technologies, so if I said anything that doesn't make any sense, my apologies.

@reZach
Copy link
Owner

reZach commented Mar 7, 2020

@Salmon42 I agree with everything you just said.

Have a take a look here and (I think) more importantly here. It'd be getting around the actual CspHtmlWebpackPlugin, or it might break it, I'm not sure yet - but I think it's the next place to start.

@reZach
Copy link
Owner

reZach commented Apr 4, 2020

@Salmon42 have you made any progress on this issue? I want to understand if it is still open or if you solved for it.

@Salmon42
Copy link
Author

I solved it only partially, by removing the CspHtmlWebpackPlugin from webpack.development.js. Which I suppose isn't a convenient way to solve this. As I was using this template for study purposes, I do not intend to release any electron app, it was sufficient enough for me. Another thing might be the wrong way of importing materialui in the project - when I began using this template, I had zero knowledge about webpack. Either way, the issue is closed for me, but there may be someone in future that will stumble upon the same situation, but they won't be able to just delete some important code to enable usage of some react UI package.

I plan to look at this issue again within few months, when I have more time and knowledge about webpack, babel and some other stuff you are using in this template.

Thanks for help for now!

@ecolman
Copy link

ecolman commented May 1, 2020

I figured this out by following your links @reZach. The material-ui doc link was to an old version and once I looked at the latest docs, I saw the answer.

CspHtmlWebpackPlugin and HtmlWebpackPlugin need to be provided a nonce, and a special meta-tag needs to be added to the index.html file for material-ui (really jss) to pick up on it. Both the index.html and index.prod.html files need to be renamed with the .ejs extension to enable templating.

Also need to add uuid for creation of the nonce:
npm i -S uuid

create-nonce.js

const { v4: uuidv4 } = require('uuid');

module.exports = function() {
  return new Buffer(uuidv4()).toString('base64');
};

webpack.development.js

const nonce = require("./create-nonce")();

  ...
  plugins: [
    new MiniCssExtractPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "app/src/index.ejs"), // notice the change to ejs
      filename: "index.html",
      nonce: nonce  // added a new property for ejs template
    }),
    new CspHtmlWebpackPlugin({
      "base-uri": ["'self'"],
      "object-src": ["'none'"],
      "script-src": ["'self'"],
      "style-src": ["'self'", `'nonce-${nonce}'`],  // added a nonce for the style-src
      "frame-src": ["'none'"],
      "worker-src": ["'none'"]
    })
  ]

index.ejs (formally index.html)

<head>
  <meta charset="UTF-8">

  <meta property="csp-nonce" content="<%= htmlWebpackPlugin.options.nonce %>" />
</head>

The same change made to webpack.development.js/index.html should be made in webpack.production.js/index-prod.html as well.

@reZach
Copy link
Owner

reZach commented May 1, 2020

@ecolman Looks good to me, thanks for sharing your solution here!
I am going to close this issue.

@reZach reZach closed this as completed May 1, 2020
@b-zurg
Copy link

b-zurg commented Jul 6, 2020

@ecolman you're the best! One addition, I found that the CspHtmlWebpackPlugin actually generates its own nonce on the script element, which conflicted with the UUID generated nonce. So I removed the UUID one in favour of the plugin-generated nonce. Was there a reason why you made your own?

@ecolman
Copy link

ecolman commented Jul 7, 2020

@b-zurg I wasn't aware that the the CspHtmlWebpackPlugin was generating it's own nonce. I basically was following the directions from Material-UI for it to work with that plugin. Can you provide a code snippet or documentation link showing how it works without a user-provided nonce?

@b-zurg
Copy link

b-zurg commented Jul 12, 2020

Well I can post my plugin call, it's almost nothing,

  new CspHtmlWebpackPlugin({
    "base-uri": ["'self'"],
    "object-src": ["'none'"],
    "script-src": ["'self'", ...(!isProd ? ["'unsafe-eval'"] : [])], //included for react-hot-loader
    "frame-src": ["'none'"],
    "worker-src": ["'none'"],
  }),

I have a boolean called isProd declared elsewhere to ensure that unsafe-eval is only included in the dev environment. This flag is necessary for react-hot-moculd to work.

The CSP appears to build a sha-based nonce. Here's my generated html:

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Security-Policy"
    content="base-uri 'self'; object-src 'none'; script-src 'self' 'unsafe-eval' 'nonce-tVZvi9VxJuouaojo+5nChg=='; style-src 'unsafe-inline' 'self' 'unsafe-eval'; frame-src 'none'; worker-src 'none'">
  <meta charset="utf-8">
  <title>myapp</title>
</head>

<body>
  <div id="app"></div>
  <script src="/window/index.js" nonce="tVZvi9VxJuouaojo+5nChg=="></script>

</body>

</html>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants