diff --git a/CHANGELOG.md b/CHANGELOG.md index ad812509..2782670c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ main ------ +* Build a Vite-based application with `vite build`, the command its own + `build` script runs, rather than with `ember build`. `ember build --help` + calls itself a "Vestigial command in Vite-based projects" and points at + that script. The output is unchanged; `silent` now quiets such a build + with `--logLevel error` rather than `ember build --silent` * Recognise an application as Vite-based from any of the six names Vite resolves its configuration from, rather than only `vite.config.js`, `vite.config.mjs` and `vite.config.ts`. An application configured in diff --git a/README.md b/README.md index 650fabba..f460fd47 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,9 @@ c.app :frontend, path: "~/projects/my-ember-app" - `path` - the path where your Ember CLI application is located. The default value is the name of your app in the Rails root. -- `silent` - this provides `--silent` option for Ember CLI commands to control verbosity of their output. +- `silent` - quiets the build. A classic application is built with + `ember build --silent`; a Vite-based one with `vite build --logLevel error`, + which keeps errors while dropping the progress output. - `package_manager` - the package manager that installs the application's NodeJS dependencies: `:npm` (the default), `:yarn`, or `:pnpm`. Name the diff --git a/lib/ember_cli/command.rb b/lib/ember_cli/command.rb index bea5925f..b79f00fc 100644 --- a/lib/ember_cli/command.rb +++ b/lib/ember_cli/command.rb @@ -14,7 +14,11 @@ def test end def build(watch: false) - ember_build(watch: watch) + if paths.vite? + vite_build + else + ember_build(watch: watch) + end end # Boots Vite's development server for an application generated with the @@ -43,6 +47,45 @@ def silent? options.fetch(:silent) { false } end + def build_environment + if EmberCli.env == "production" + "production" + else + "development" + end + end + + # The Vite-based blueprint (`ember-cli >= 6.8`) + # + # Builds the application the way its own `build` script does. + # `ember build` still drives such a build today, but `ember build --help` + # calls it a "Vestigial command in Vite-based projects" and has dropped + # every option but `--environment`, `--suppress-sizes` and + # `--output-path`. + # + # `--emptyOutDir` is needed because the output directory is outside the + # Ember application, where Vite leaves stale files in place unless asked + # to clear them. + def vite_build + line = Terrapin::CommandLine.new(paths.vite, [ + "build", + "--mode :mode", + "--outDir :output_path", + "--emptyOutDir", + ("--logLevel error" if silent?), + ].compact.join(" ")) + + line.command( + mode: build_environment, + output_path: paths.dist, + ) + end + + # The classic blueprint + # + # Builds the application with `ember build`, which watches for changes + # when asked. A Vite-based project has no equivalent: `ember build` there + # refuses `--watch`, and its development server watches instead. def ember_build(watch: false) line = Terrapin::CommandLine.new(paths.ember, [ "build", @@ -59,13 +102,5 @@ def ember_build(watch: false) watcher: process_watcher, ) end - - def build_environment - if EmberCli.env == "production" - "production" - else - "development" - end - end end end diff --git a/spec/lib/ember_cli/command_spec.rb b/spec/lib/ember_cli/command_spec.rb index 4a786a09..932c1f81 100644 --- a/spec/lib/ember_cli/command_spec.rb +++ b/spec/lib/ember_cli/command_spec.rb @@ -106,8 +106,38 @@ end end + describe "#build for a Vite-based application" do + it "builds a `vite build` command writing to the output path" do + paths = build_paths(vite?: true, vite: "path/to/vite", dist: "path/to/dist") + command = build_command(paths: paths) + + expect(command.build).to match(%r{path/to/vite build}) + expect(command.build).to match(/--mode 'development'/) + expect(command.build).to match(%r{--outDir 'path/to/dist'}) + expect(command.build).to match(/--emptyOutDir/) + end + + it "does not pass the flags `ember build` takes" do + paths = build_paths(vite?: true, vite: "path/to/vite") + command = build_command(paths: paths, options: { watcher: "events" }) + + expect(command.build(watch: true)).not_to match(/--watch/) + expect(command.build(watch: true)).not_to match(/--environment/) + end + + it "quiets the build when configured to be silent" do + paths = build_paths(vite?: true, vite: "path/to/vite") + + expect(build_command(paths: paths).build).not_to match(/--logLevel/) + + command = build_command(paths: paths, options: { silent: true }) + + expect(command.build).to match(/--logLevel error/) + end + end + def build_paths(**options) - double(options).as_null_object + double({ vite?: false }.merge(options)).as_null_object end def build_command(**options)