3

I am developing a chrome extension using vue 3, vue-router and vuex based on Kocal's project which uses vue-cli under the hood. I used whenever possible Single File Components with extensive use of vue bindings. Everything works perfect on development mode but I recently tried to build the application for production and I encountered this error with partial rendering:

chunk-vendors.f6de00a6.js:11 EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".

After a few days of digging, my understanding is that either webpack or vue compiling system is messing with CSP by referring/injecting code through eval scripts. As I am fairly new to this, it's hard for me to read to distinguish what I can do.

I tried different approaches:

  • defining $vue alias to a runtime only build in vue.config.js (supposedly removing unsafe eval by having code compiled before runtime but ending with a new error: Uncaught TypeError: Object(...) is not a function for o=Object(n["withScopeId"])("data-v-21ae70c6");)
  • using render() function at root
  • adding "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", to manifest.json
  • switching a component to render() to see if I have better chance with the partial rendering, but ending up with nothing being displayed although having console.log from render being executed.
  • Adding a config to chainWebpack splitting manifest and inline manifest on vue.config

What puzzles me is that I can't shake off the unsafe-eval, with at best a partial display, at worst a blank page. Bindings seem to be shaken off regardless and using a router-link to change page will give a blank page.

Edit: After digging through compiled code from webpack and setting minimize opt to false, it seems the error comes from a vendor: vue-i18n

2 Answers 2

1

The eval is likely coming from Webpack, due to an issue with global scoping.
see link for more detail https://mathiasbynens.be/notes/globalthis

Could you try adding this configuration to vue.config.js

module.exports = {
  configureWebpack: {
    node: {
      global: false
    },
    plugins: [
      new webpack.DefinePlugin({
        global: "window"
      })
    ]
  }
};
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the suggestion. I saw the node: false config somewhere but haven't tried it. I added what you suggest to my vue.config.js, but I the same issue persists (partial rendering with eval errors)
I have been testing and testing again and the fact that I have at least partial rendering seems to indicate that webpack does at least some part of the compilation correctly. If I was to change vue$ alias to a runtime only build, I have indeed full blank screen. I think the issue might be somewhere else.
🤔if runtime-only Vue is causing blank, it seems to indicate that the template is not being compiled, but from the repo don't see a reason why that would be happening.
It is normal, vue-cli uses webpack to pre-compile .vue, and I was giving him the runtime only vue.js for this pre-compilation. It might not give much, but at least part of the .vue files are compiled.
1

tl;dr: Check your dependencies/packages, including those you wouldn't think they use unsafe-eval.

After digging into webpack internals and components building for vue3, here are the takeaways:

  • using Single File Components and default vue-cli config is ok as it will indeed just need vue runtime, so no unsolicited unsafe-eval
  • webpack config as below works:
  module.exports = {
    configureWebpack: {
      plugins: [
        new webpack.DefinePlugin({
          global: "window" // Placeholder for global used in any node_modules
        })
      ]
    },
    ...
  };
// Note that this plugin definition would break if you are using "unit-mocha" module for vue-cli

In the end, the issue was a dependency I was using for i18n vue-i18n@next, after removing it and switching to chrome's i18n way, it's now working.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.