编辑:这看起来像这个Unresolved Question的副本。我将此标记为已回答或删除吗?
我在Vue CLI 3应用程序中使用来自workbox-webpack-plugin的InjectManifest。我注入的自定义服务工作者负责处理Firebase云消息传递(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
});
但是,webpack似乎没有触及此代码,因为输出服务工作者仍然读取process.env.VUE_APP_FCM_SENDER_ID
而不是硬编码密钥。
如何通过webpack运行我的服务工作者以解决环境变量?
现在对你来说可能为时已晚,但对于其他人来说,这就是我如何解决这个问题。此过程仍然使用.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"
}
希望,这应该成功。我希望有更清洁的方法来做到这一点,所以我很高兴知道其他人的解决方案。
我遇到了同样的问题,关键是让webpack构建过程输出它使用的env变量,以便将它们导入服务工作者。这样您就不必将env var定义复制到预处理服务工作者的其他内容中(因为该文件位于源代码控制中,因此无论如何都是混乱的)。
// <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)
}
}
vue.config.js
或vue-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' })
],
},
}
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
目录,但希望比我聪明的其他人能够解决这个问题。