Currently when deploying to now 2.0 we force all dependencies to be devDependencies, the reason for this is creating the smallest possible lambda.
This however introduces some issues:
next build --lambdas bundles imported modules and no longer uses externals for this reason.next.config.js that uses any module, most commonly a Next.js plugin like @zeit/next-css loading next.config.js in production will fail because of the module not being there. However this opens up the question: why is next-css being loaded on cold start in production.One solution is forcing phases to be used, documentation can be found here: https://github.com/zeit/next.js#custom-configuration
However there are alternatives, for example:
next.config.ts or similar. At first glance this seems like a solution, however it doesn't solve the build-time modules being loaded in production mode.publicRuntimeConfig and assetPrefix (which does work at runtime), which is for example used by Trulia's appshell.I'd love to know how people are using next.config.js currently. From what I've seen the vast majority looks like the equivalent of:
const thePlugin = require('theplugin')
module.exports = thePlugin({})
Issue reference for Now 2.0: #5750
For now this issue is just a writeup of one issue regarding serverless execution, I don't have a definitive opinion about this yet, but I wanted to write down my thoughts on the subject so that we can get the community involved and work towards a solution 👍
I suggest to follow what Gatsby does and split config into universal next.browser.js and server-side next.config.js. For lambda deployment next.config.js would be used during build and not bundled into production, while next.browser.js would be bundled and used for things like custom routing, app plugins like App or Document decorators, and any universal code.
Also referencing: https://github.com/zeit/next.js/issues/1852#issuecomment-440808597
I think it's a good idea to make next.config.js build only.
Also, if the build script becomes next build --target=lambda, maybe it would make sense to replace phase by target ?
I use next.config.js for customized webpack configuration, which is a pain to get it right universally, that's why nextjs plugins are god-send.
And for what i see, the purpose of next.config.js is for build phase only, regarding on local or on cloud or not, because in the end what we want to run in production is what got bundled already.
we'd still need a way to allow publicRuntimeConfig and assetPrefix (which does work at runtime)
@timneutkens Does this also include serverRuntimeConfig? We set both publicRuntimeConfig and serverRuntimeConfig values from environment variables at start time in our Docker containers.
@goldenshun correct, both are runtime values currently
Seems like this could help relieve this error:
https://spectrum.chat/zeit/general/unable-to-import-module-now-launcher-error~2662f0ba-4186-402f-b1db-2e3c43d8689a
Watching these Serverless updates (along with monorepo coupled with move to next-server) has been great. Truly, truly tremendous work! Not just in next itself but with the builders as well!
I mainly use next.config.js for customized webpack, next specific settings, and grabbing Environment Variables set via now.json for the build process. On most projects I do not use plugins. (Subject to change, or adapt to whatever comes of this RFC. 😀️ )
Below is a deeper dive in regards to Environment Variables. If it is off-topic, please disregard and I can share this elsewhere.
Using phases as @balupton linked to, I've been able to do serverless builds (w/o config), after the initial build (w/ config).
For customized webpack I frequently use resolve.alias.
const path = require('path') const customAlias = {
'@components': path.resolve(__dirname, './components/'),
// ... @data, @lib, etc.
}
config.resolve.alias = Object.assign(config.resolve.alias, customAlias)
Which works just fine.
On my end, I cannot seem to get any Environment Variables at the moment from now.json that I use in next.config.js. (Which has been alluded to here.)
What I would hope could be an option, would be the ability to get Environment Variables at build time, which could be used to create the lambda (via babel and/ or next).
I've tried a bevy of different ways within these three of attempting to do it with now.json:
publicRuntimeConfig: Will not grab process.env.*, nor update/accessible via the build (next/config).dotenv, dotenv-webpack, now-env: My own testing for good measurenew webpack.DefinePlugin: Does not seem to work. Does not pass the values I attempt to put in it at least. Even hard-coding values and not attempting to pull from process.env.*For now, I am using:
babel-plugin-transform-defineWhere it still will not grab process.env.*, but I can provide fallbacks and then babel will update the build code as appropriate. So I'm kind of creating a .env file all the same.
So for now I have turned off :octocat: GitHub Deployments in this example as I need to share that ".env"-like file directly with now (and doesn't exist in repo).
https://zeit.co/docs/v2/deployments/configuration#build.env
Didn't know we needed to (or could) wrap the Environment Variables needed as part of the build within a build object in now.json.
🤯️ 🤯️ 🤯️
"build": {
"env": {
"ENV_VARIABLE": "@secret--env_variable"
}
},
🤯️ 🤯️ 🤯️
EDIT:
If you are using now-env locally you'll need to set the root env with the same variables (in addition to build for your deployment). So a little duplication at the moment, but it would explain the conflicts I was having earlier with things working locally with just env being set, and not during the build on now. 🤣️
We've solved this by not bundling next.config.js in the serverless target, disallowing publicRuntimeConfig and introducing a new env key: https://github.com/zeit/next.js#build-time-configuration
Documented under https://github.com/zeit/next.js#serverless-deployment
@timneutkens any way to add @secret to the next.config.json ?
@timneutkens is there no way to provide runtime configuration at all to Lambdas now? Ideally we wouldn't need to rebuild the app to have it go to different backends.
Currently we have Lambdas with different environments for dev, stage & live. They then use the same Lambda package but with different env-variables. Ideally we could use the same approach for our Next.js app 🤔
It feels a bit weird that our build artefacts have to include the env-specific config...
@timneutkens is there no way to provide runtime configuration at all to Lambdas now? Ideally we wouldn't need to rebuild the app to have it go to different backends.
Currently we have Lambdas with different environments for dev, stage & live. They then use the same Lambda package but with different env-variables. Ideally we could use the same approach for our Next.js app 🤔
It feels a bit weird that our build artefacts have to include the env-specific config...
Completely agree. This is definitely a backwards step. We intend to only build once and deploy to different envs. This change looks likely to kill quite a bit of the enthusiasm behind moving to lambda
Most helpful comment
Completely agree. This is definitely a backwards step. We intend to only build once and deploy to different envs. This change looks likely to kill quite a bit of the enthusiasm behind moving to lambda