如何根据环境变量自定义我的Service Worker?

时间:2019-01-24 22:38:31

标签: webpack service-worker vue-cli-3 workbox-webpack-plugin

编辑:这看起来像是此Unresolved Question的副本。 我将其标记为已回答还是删除?

我正在Vue CLI 3应用程序内的workbox-webpack-plugin中使用InjectManifest。我要注入的自定义服务人员已经处理了Firebase Cloud Messaging(FCM)。我需要根据自己的环境(本地,暂存和生产环境)侦听来自不同发件人的消息。

理想情况下,service-worker.js看起来像这样:

importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

firebase.initializeApp({
    'messagingSenderId': process.env.VUE_APP_FCM_SENDER_ID
});

但是,由于输出服务工作者仍然读取process.env.VUE_APP_FCM_SENDER_ID而不是硬编码的密钥,因此webpack似乎没有触及该代码。

如何通过Webpack运行服务工作者以解决环境变量?

2 个答案:

答案 0 :(得分:2)

现在对您来说可能为时已晚,但是对于其他人来说,这就是我继续解决这个问题的方式。 此过程仍将.env文件用于与环境相关的变量。
这个想法是创建一个新脚本来加载.env文件,该脚本创建一个新文件,其中填充了.env文件中的变量。
构建过程完成后,我们只需将新生成的文件导入sw.js中即可使用。

这是步骤。
首先创建一个名为swEnvbuild.js的文件,它将是您在webpack

之后运行的脚本
//swEnvBuild.js - script that is separate from webpack
require('dotenv').config(); // make sure you have '.env' file in pwd
const fs = require('fs');

fs.writeFileSync('./dist/public/swenv.js',
`
const process = {
  env: {
    VUE_APP_FCM_SENDER_ID: conf.VUE_APP_FCM_SENDER_ID
  }
}
`);

第二,我们在swEnvBuild.js中导入从swenv.js生成的名为sw.js的文件。

// sw.js
importScripts('swenv.js'); // this file should have all the vars declared
console.log(process.env.VUE_APP_FCM_SENDER_ID);

最后,要使用一个命令运行此命令,只需在npm脚本中添加以下内容(假设您正在运行Linux / Mac)。

scripts: {
  "start": "webpack && node swEnvBuild.js"
}

希望这可以解决问题。我希望有更清洁的方法可以做到这一点,所以我很高兴也知道其他人的解决方案。

答案 1 :(得分:0)

我遇到了同样的问题,关键是要使webpack的构建过程输出它使用的env var,以便可以将其导入到service worker中。这样一来,您不必将环境变量的定义复制到可以对服务工作者进行预处理的其他内容中(无论如何,这都很混乱,因为该文件在源代码控制中)。

  1. 创建一个新的Webpack插件

    // <project-root>/vue-config/DumpVueEnvVarsWebpackPlugin.js
    const path = require('path')
    const fs = require('fs')
    
    const pluginName = 'DumpVueEnvVarsWebpackPlugin'
    
    /**
     * We to configure the service-worker to cache calls to both the API and the
     * static content server but these are configurable URLs. We already use the env var
     * system that vue-cli offers so implementing something outside the build
     * process that parses the service-worker file would be messy. This lets us
     * dump the env vars as configured for the rest of the app and import them into
     * the service-worker script to use them.
     *
     * We need to do this as the service-worker script is NOT processed by webpack
     * so we can't put any placeholders in it directly.
     */
    
    module.exports = class DumpVueEnvVarsWebpackPlugin {
      constructor(opts) {
        this.filename = opts.filename || 'env-vars-dump.js'
      }
    
      apply(compiler) {
        const fileContent = Object.keys(process.env)
          .filter(k => k.startsWith('VUE_APP_'))
          .reduce((accum, currKey) => {
            const val = process.env[currKey]
            accum += `const ${currKey} = '${val}'\n`
            return accum
          }, '')
        const outputDir = compiler.options.output.path
        if (!fs.existsSync(outputDir)) {
          // TODO ideally we'd let Webpack create it for us, but not sure how to
          // make this run later in the lifecycle
          fs.mkdirSync(outputDir)
        }
        const fullOutputPath = path.join(outputDir, this.filename)
        console.debug(
          `[DumpVueEnvVarsWebpackPlugin] dumping env vars to file=${fullOutputPath}`,
        )
        fs.writeFileSync(fullOutputPath, fileContent)
      }
    }
    
  2. 在vue-cli配置中使用插件(vue.config.jsvue-config/config.default.js,如果您的配置分为几个文件)

    // import out plugin (change the path to where you saved the plugin script)
    const DumpVueEnvVarsWebpackPlugin = require('./DumpVueEnvVarsWebpackPlugin.js')
    
    module.exports = {
      // other stuff...
      configureWebpack: {
        plugins: [
          // We add our plugin here
          new DumpVueEnvVarsWebpackPlugin({ filename: 'my-env-vars.js' })
        ],
      },
    }
    
  3. 在我们的Service Worker脚本中,我们现在可以导入使用Webpack插件编写的文件(在构建发生并且Service Worker不在开发人员模式下运行后,该文件将在那里。安全)

    importScripts('./my-env-vars.js') // written by DumpVueEnvVarsWebpackPlugin
    const fcmSenderId = VUE_APP_FCM_SENDER_ID // comes from script imported above
    console.debug(`Using sender ID = ${fcmSenderId}`)
    
    // use the variable
    firebase.initializeApp({
        'messagingSenderId': fcmSenderId
    })
    

这不是完美的,但肯定可以完成工作。这是D-R-Y,因为您只需在一个位置定义所有环境变量,并且整个应用程序使用相同的值。另外,它不处理源代码管理中的任何文件。我不喜欢该插件在Webpack生命周期中运行得太早,因此我们必须创建dist目录,但希望比我更聪明的人也可以对此进行修复。