Search code examples
vue.jswebpackgoogle-chrome-extensionvue-clivuejs3

Vue.js 3 extension breaks while using "vue-cli-service build" due to unsafe-eval


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


Solution

  • 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.