Assets Nodejs
Jets can build a Docker image with the Nodejs runtime installed for apps that need it. For Rails, Nodejs is typically useful for compiling assets that use Node ecocystem libraries.
Install NodeJS
The default config.assets.build.nodejs.enable = "auto"
means Jets will auto-detect whether or not to install NodeJS.
config/jets/deploy.rb
Jets.deploy.configure do
config.assets.build.enable = true
config.assets.build.nodejs.enable = "auto"
# config.assets.build.nodejs.version = "20.12.1" # default a stable nodejs version
end
When a package.json
or yarn.lock
is detected in the source code, Jets will install nodejs and yarn.
Node Version Precedence
Jets auto-detects what Nodejs version to install for the Docker image it builds. The auto-detection precedence works in this order:
- config
- .tool-versions or .nvmrc
- default
It’s recommended to use #2 .tools-version or .nvmrc
config
You can configure the NodeJS version to use with a config. It takes the highest precedence.
config/jets/deploy.rb
Jets.deploy.configure do
config.assets.build.nodejs.version = "20.12.2"
end
Gemfile
Jets will evaluate the Gemfile
and use the NodeJS version if there’s a specified ruby
version.
Gemfile
ruby "20.12.2"
.tool-versions or .nvmrc
If your project has a .tool-versions
(asdf) or .nvmrc
, Jets installs that version. If both .tool-versions
and .nvmrc
exist, the .tool-versions
takes higher precedence.
default
The Jets default NodeJS version may change in the future. See “NodeJS Version Default” below.
NodeJS Version Default
Jets installs a version of nodejs that we feel is stable. This may mean that the default version is different from the latest LTS version. We cannot guarantee the default version won’t change. The reasons for this are elaborated below.
The NodeJS world tends to move quickly. In some ways, this is great for rapid innovation. However, it can make it a tough experience for someone who does not work on node and javascript on a daily basis. One of the top visited pages from the boltops/jets community forums is for webpack issues. 🤦🏻♂️
It seems like some npm package is upgraded every couple of months, which happens to break backward compatibility with other libraries or old configuration schema settings. Speaking from real-world experience, it’s the Wild West.
- Over the years, schema or interfaces for configurations like
babel.config.js
,.browserslistrc
,config/webpacker/environment.js
,postcss.config.js
,config/webpacker.yml
change in breaking ways. - Here are just some examples: webpacker 2059, webpacker 2202, webpacker 2342, jetpacker 4, digital envelope routines::unsupported Error.
- The error messages could be better, particularly when webpack breaks. I have read a few javascript books Douglas Crockford JavaScript books: JavaScript: The Good Parts and How JavaScript Works, and David Flanagan’s JavaScript: The Definitive Guide. It’s funny that the Good Parts book is short compared to other general Javascript books. 😄
- I have also worked with both reactjs and vuejs. I’ve even released packages for npm. Albeit it’s a small humble library: @rubyonjets/ujs-compat. Generally, I found that the JavaScript world can still be a frustrating experience. The error messages may be clearer for a node/javascript everyday developer.
- I have found it’s usually faster to treat things like a black box when there have been webpack issues. IE: Upgrade yarn and node, regenerate the configuration files, and see if that fixes issues. Sometimes, you have to dig deeper, and that takes a decent amount of time.
- DHH also discusses the move away from node tools like esbuild, rollup.js, and webpack in this Rails 7 will have three great answers to JavaScript in 2021+.
- Ultimately, there are only so many hours in a day.
Thus, we may change the default node version more liberally than other components. If you need specific versions, you should explicitly set them. You can also precompile your assets locally and add them to git before deployment.
Reference
The table below covers each setting. Each option is configured with config.OPTION
. The config.
portion is not shown for conciseness. IE: logger.level
vs config.logger.level
.
Name | Default | Description |
---|---|---|
assets.build.detect_local | true | If public/assets/manifest-*.js is detected in the source code, Jets assumes you have locally precompiled assets and the remote runner will not attempt to compile assets in the remote runner docker build process. |
assets.build.enable | “conditional” | When Rails, it’s set to true. For other frameworks like sinatra, it’s set to false. |
assets.build.nodejs.enable | auto | The auto value means that it will be auto-detected. When a package.json is detected in the source code, it’ll assume you’ll need nodejs and yarn installed. |
assets.build.nodejs.version | 20.12.1 | The nodejs version to use. We try to default to the latest LTS node. |
assets.build.nodejs.deployment_stage | true | When is nodejs.enable , it will install for both build and deployment stages for the multi-stage docker build process. You can use this to disable it for the deployment phase. This means the Docker image you’re running won’t have access to the nodejs runtime. It’s only use to build artifacts. |
assets.build.precompile_command | “conditional” | When Rails, the default command is a jets precompile_assets.sh , which calls rails assets:precompile if it’s available. Otherwise, it is nil . |
assets.upload.cache_control | nil | The cache control header to use for assets uploaded to s3. Example: public, max-age=3600 . |
assets.upload.enable | true | Upload the assets from assets.upload.folders , IE: public, to s3. |
assets.upload.folders | [“public”] | Folders to upload to s3. |
assets.upload.max_age | 3600 | The max age in seconds for the cache control header. This is a shorter way to set the cache_control. IE: 3600 => public, max-age=3600 |