Skip to content

Revisit css:build using the yarn:install task #45

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

Closed
wants to merge 1 commit into from

Conversation

zarqman
Copy link
Contributor

@zarqman zarqman commented Nov 17, 2021

This restores use of the yarn:install task from #42, but adds a conditional for Rails 6.x to parallel existing behavior on those Rails versions, which addresses #43.

This does mean that yarn install will be skipped on Rails 6.x if bin/yarn doesn't exist, but this was already true for assets:precompile with webpacker anyway.

Rails 6.x apps migrating from webpacker will usually have bin/yarn already. Apps migrating from just sprockets without webpacker may not, but this should be infrequent. Rails 6.x apps that want yarn install to run automatically can:
a) create bin/yarn,
b) add their own task dependency on yarn:install, or
c) include yarn:install when building css or precompiling: rails yarn:install build:css or rails yarn:install assets:precompile.

Rails 7 apps will continue to call yarn:install automatically, which uses yarn via the PATH and not bin/yarn

Background:
Rails 6.x's yarn:install requires bin/yarn to exist. If not present, it silently skips adding a dependency on yarn:install from assets:precompile.

Reasoning:
I think there's still value in using the yarn:install task as it performs more than a simple yarn install. In addition to ensuring yarn install only runs once (via rake's dependency mechanism), yarn:install also sets NODE_ENV and adds some flags to the execution. If an app needs to customize yarn:install, it also provides a single point to do so.

Another alternative is to remove yarn install entirely and let apps call yarn:install on their own (or even yarn install --custom-flags), just like they call bundle install. Build scripts that still want to use the task could simply add it before precompile, ie: rails yarn:install assets:precompile.

@dhh
Copy link
Member

dhh commented Nov 19, 2021

I'd like to find a different path here. We're only leaving yarn:install on Rails as a temporary step. Rails 7+ should preferably not have any affiliation with yarn natively. So I don't think we should continue to build upon this.

Perhaps a different could be that Rails 7 will have a default option that means that yarn:install is not hooked onto assets:precompile?

@zarqman
Copy link
Contributor Author

zarqman commented Nov 19, 2021

It sounds like you're saying yarn:install will be removed from Rails 7.1 and should be considered deprecated on 7.0?

Known issues:

  • yarn install can get called multiple times
  • Rails 6.x's yarn:install requires bin/yarn
  • Some apps will want to call yarn install with non-default arguments

To avoid running yarn install multiple times, I see three potential paths:

  1. Use a centralized rake task, yarn:install, to take advantage of rake's run-once semantics.
    1a) Define this once in Rails, as now.
    1b) Define yarn:install in both cssbundling-rails and jsbundling-rails each with if-not-yet-defined conditions. Remove from Rails 7 completely. For Rails 6.x, likely still need the 'invoke if bin/yarn exists' test outlined in this PR. The NODE_ENV handling and flags to yarn likely get dropped to keep the duplicate yarn:install definitions simpler.

  2. Maintain global state between cssbundling-rails, jsbundling-rails, and wherever else.
    In some apps here, we conditionally override yarn:install into a no-op so we can run yarn install in advance with our own choice of params. Building on this pattern, to both cssbundling-rails and jsbundling-rails, we could add something like (untested):

task :build do
  unless ENV["SKIP_YARN_INSTALL"]
    ENV["SKIP_YARN_INSTALL"] = "1"  # avoid dupe runs
    unless system("yarn install")
      # ...error message
    end
  end
  # ... continue with yarn build or build:css
end

This essentially uses the ENV as a global state variable, but with the added benefit of also letting it be set externally when yarn install isn't wanted at all.

  1. Limit yarn install to css:install:* and javascript:install:* tasks, and remove it from everywhere else. Let apps run yarn install on their own, just like they're expected to run bundle install.
    Apps could still add their own yarn:install task and dependency from assets:precompile -> yarn:install if wanted, ie: to support their particular PaaS of choice.
    This has the additional benefit of reducing touchpoints to yarn, which might make it easier for individual apps to override existing tasks to switch to npm if desired.

FWIW, my lean is toward (3), in part because it improves the speed of the dev cycle by not needing to wait on yarn install for bin/dev startup or running certain tests.

How do those strike you and what path forward seems best to you?

@dhh
Copy link
Member

dhh commented Dec 2, 2021

Yeah, I don't want to see anything Yarn-related in Rails itself going forward. So #3 sounds like the right path.

@zarqman
Copy link
Contributor Author

zarqman commented Dec 15, 2021

Replaced by #50 which implements (3) above. Also see parallel PR in rails/jsbundling-rails#57.

@zarqman zarqman closed this Dec 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants