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:
$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");
)render()
function at root"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
to manifest.json
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.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
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:
unsafe-eval
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.