-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for compile-time vs runtime variables #1217
Comments
This is too-tightly coupled to the constraints of a specific platform. Also looks like this is possible to solve in userland, so it should be done in userland. |
I don't think its specific to Heroku. Deploying an SPA to use a staging API and then later deploying it to production seems like a pretty common workflow. Right now, there is no elegant workflow to deploy to different environments, without having to rebuild, thus ending up with different builds for different environments, when the only difference is the API Url. There is also a discussion surrounding the topic over here: facebook/create-react-app#578 (comment) I feel like this is a topic a web app framework should address, but everybody tries to avoid. At least some best practice guidelines would be great. |
Topic: support for runtime environment, e.g., SITE_URL and such The issue is that Webpack has already packed everything, meaning that there is no way to use API_URL as I used it. Links: https://12factor.net/ https://github.com/mars/create-react-app-buildpack#compile-time-vs-runtime vuejs/vue-cli#1217 facebook/create-react-app#578 https://stackoverflow.com/questions/45111936/passing-environment-variable-to-webpack-2-after-build
I have been plagued by this problem for many years now, especially since we now use ephemeral review environments in our Kubernetes cluster. At first, I just dealt with it, "no problem" I said "we can just run webpack before serving up requests". This works fine, but there's a fundamental problem, running a static site requires significantly less RAM and CPU than running webpack on a large project. So, you are now provisioning environments that have huge CPU and RAM so you can compile webpack just in time. This is expensive, and honestly a terrible idea. Then I thought to myself "Why don't I just create a simple node script that just finds and replaces all instances of I ended up solving this issue, as Evan suggested above, in userland. It's not an ideal setup by any means, but I can now compile my entire app in a continuous deployment pipeline, bake that code into a Docker container and run the app anywhere with no issues. The solution I came to is regex matching the hostname and changing the environments variables that way. here is the actual code I'm using.
I hope this helps some people. <3 |
Obviously this is a trade-off because you can't benefit the dead-code elimation at build-time with UglifyJS, however in most cases if you are looking into improve build size you can use async imports and code splitting. |
Run-time variables are a must for me too. I solved this by using JS config variables within the app (so that when the app is compiled, it refers to e.g. window.appConfig.API_ROOT). Then within the CI pipeline, a JS file is created defining all the config values for that particular environment.
In reality it's a little more complex as the JS file within the CI workflow grabs the config values from a centralised secrets store. |
For SSR and browser both side, src/app/runtime-config.jsan isomorphic module to fetch a config json file in runtime (after build in production mode) import 'isomorphic-fetch'
import serverConfig from '../../vue.config'
const IS_SSR = process.server
const WEB_SERVER_URL = IS_SSR ? `http://${serverConfig.pluginOptions.ssr.host}:${serverConfig.pluginOptions.ssr.port}` : location.origin
const RUNTIME_CONFIG_URL = `${WEB_SERVER_URL}${process.env.BASE_URL}config/runtime.json`
let cachedConfig = null
export default async function getRuntimeConfig () {
if (cachedConfig) return cachedConfig
return fetch(RUNTIME_CONFIG_URL)
.then(res => res.json())
.then(config => {
cachedConfig = IS_SSR ? config.ssr : config.browser
console.log(cachedConfig)
return cachedConfig
})
} public/config/runtime.jsona config json example {
"browser": {
"GRAPHQL_SERVER_URL": "https://api.dev.redacted--.kr/graphql"
},
"ssr": {
"GRAPHQL_SERVER_URL": "http://api-gateway.dev.svc.cluster.local/graphql"
}
} src/app/any-module.jsusage example import getRuntimeConfig from './runtime-config'
...
const config = await getRuntimeConfig()
const HTTP_ENDPOINT = config.GRAPHQL_SERVER_URL It works! |
What problem does this feature solve?
When developing in a Heroku pipeline, environment variables are hardcoded in the build process for a staging app. When that app is promoted to production, the build is not recompiled, and there is no way to change the values passed to those variables. For example, the value of a variable like VUE_APP_API_URL will likely need to change from the staging API/database to the production API/database. Using vue-cli modes and setting different values in .env.staging and .env.production only works if the app is being recompiled for the production environment.
What does the proposed API look like?
See the solution implemented for create-react-app as outlined here: https://github.com/mars/create-react-app-buildpack#compile-time-vs-runtime.
The text was updated successfully, but these errors were encountered: