最近没事做 Chrome 插件时,突发奇想,觉得可以用 Vue 来构建,于是折腾了两天完成,随手总结下。

尝试与思考过程

由于手头有一个现成的脚手架,于是在产生这个想法后,我立刻将自己的 Vue 脚手架拉到插件目录中,企图直接使用。编译本地运行,似乎一点问题也没有,然而当我配置好插件信息加载到 Chrome 中时,发现页面一片空白,一时不知原因为何。

接下来我在查了一些资料后得知 Chrome 插件环境下的 内容安全策略(CSP) 为了安全会禁止某些函数的执行,于是Vue.js中的模板渲染会遇到问题。接着我回到Vue.js的文档中查找解决方法,找到了关于CSP环境下的说明

Some environments, such as Google Chrome Apps, enforce Content Security Policy (CSP), which prohibits the use of new Function() for evaluating expressions. The full build depends on this feature to compile templates, so is unusable in these environments.

问题出在了模板渲染函数使用了new Function,官方这段文档建议我们使用 CSP 版本Vue.js,然而我到处找却并没有找到 CSP 版本Vue.js 2.0,最新的也还是 Vue.js 1.0

找不到可用的 CSP 版本 的,我将目标放在插件配置上。查看了插件开发文档后,看到这么一段关于插件 CSP 配置的,在 manifest.json 中加入如下一行,问题解决。

  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",

然而这么做,很不科学也不安全。除了这种方法,就只能使用低版本的 Vue.js 么?实际上并不是,不知道为何 Vue.js 的官方文档没有提及。

新建一个 Vue.js 的项目的时候,有一个如下的选项:

  ? Vue build (Use arrow keys)
  ❯ Runtime + Compiler: recommended for most users 
    Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere

实际上,当我们选择 Runtime-only 的话,所有的模板都将会在编译的时候转换成函数,而不是运行时生成了。这样的话,就完全兼容了 CSP,于是我开始修改我现有的脚手架。

具体解决步骤

  1. 安装模板编译依赖项
    npm install vue-template-compiler@xxx # xxx 需要和你当前的 vue 版本一致
  2. 修改 new Vue 中渲染方式
    new Vue({
      el: '#app',
      router,
      store,
      template: '<App/>',
      components: { App },
    });

    改为

    new Vue({
      el: '#app',
      router,
      store,
      render: h => h(App),
    });
  3. 重新编译,运行,问题解决。

参考