Skip to content
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

feat!: always use package_json for managing node packages #430

Merged
merged 24 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e38e764
feat!: always use `package_json` for managing node packages
G-Rath Mar 8, 2024
b668371
docs: update readme
G-Rath Mar 8, 2024
18408b6
fix: include additional lockfiles in default watched paths
G-Rath Mar 8, 2024
680e86e
fix: remove reference to `yarn install` in manifest error message
G-Rath Mar 8, 2024
ac20d2e
test: rename helper
G-Rath Mar 8, 2024
c676b25
chore: remove unused param
G-Rath Mar 8, 2024
5052248
docs: add note about (lack of) interaction with `corepack`
G-Rath Mar 9, 2024
8dc4e5c
docs: make it clearer that `packageManager` should be set as part of …
G-Rath Mar 9, 2024
e9c3b21
fix: reword error message
G-Rath Mar 14, 2024
5ba68f8
feat: merge with existing `package.json` rather than replacing it com…
G-Rath Mar 24, 2024
58c0ff1
feat: add package manager checker
G-Rath Mar 24, 2024
b7c42db
docs: update readme to reflect the change we want
G-Rath Mar 25, 2024
a67041a
feat: ensure the `packageManager` field is set when installing
G-Rath Mar 25, 2024
c99bf5b
feat: check the package manager is obvious before running commands
G-Rath Mar 25, 2024
26d537d
test: deduplicate temp directory helper
G-Rath Mar 25, 2024
6515c73
feat: check the manager is obvious as part of `shakapacker:check_mana…
G-Rath Mar 25, 2024
cab244d
refactor: make manager checker a utility
G-Rath Mar 25, 2024
bf5691a
feat: check the manager is obvious as part of `shakapacker:info`
G-Rath Mar 25, 2024
791cc5a
feat: error if package manager is not obvious
G-Rath Mar 25, 2024
f08a313
refactor: clean up `package_json` requires and methods
G-Rath Mar 25, 2024
f66292a
feat: make error message a bit nicer
G-Rath Mar 26, 2024
e6ae3c0
chore: add `packageManager` to top level `package.json`
G-Rath Mar 26, 2024
9032d08
feat: add railtie initializer to check package manager version
G-Rath Mar 26, 2024
c073e1e
Add packageManager field to dummy app package.json
tomdracz Mar 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/generator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
matrix:
os: [ubuntu-latest]
ruby: ['2.7', '3.0', '3.1', '3.2']
use_package_json_gem: ['true', 'false']
gemfile:
- gemfiles/Gemfile-rails.6.0.x
- gemfiles/Gemfile-rails.6.1.x
Expand All @@ -46,5 +45,3 @@ jobs:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- run: bundle exec rake run_spec:generator
env:
SHAKAPACKER_USE_PACKAGE_JSON_GEM: ${{ matrix.use_package_json_gem }}
7 changes: 0 additions & 7 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,3 @@ jobs:

- name: Ruby specs
run: bundle exec rake run_spec:gem
env:
SHAKAPACKER_USE_PACKAGE_JSON_GEM: "false"

- name: Ruby specs
run: bundle exec rake run_spec:gem
env:
SHAKAPACKER_USE_PACKAGE_JSON_GEM: "true"
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Changes since the last non-beta release.

Use `generateWebpackConfig` instead.

- Use `package_json` gem to manage Node dependencies and commands, and use `npm` by default [PR 430](https://github.com/shakacode/shakapacker/pull/430) by [G-Rath](https://github.com/g-rath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on npm default rationale - how did we land here? Traditionally yarn was the only one supported so this feels like a fairly inconvenient change for upgrade potentially. Is it just the nature of package-json gem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that aligns with the default for Node / package.json - npm is the default package manager that ships with Node and so in the absence of a packageManager in package.json, is what gets used; that's also why npm is not actually listed as a supported package manager with corepack.

Really the biggest impact of this should be when installing packages, which as of v8 we won't do automatically - running commands with a different package manager is usually fine (I use my nrun script locally for running commands which uses always npm under the hood, and not had any issues), so this should primarily come up when you're doing shakapacker:install which is typically at the start of a fresh project so should just mean having to spend 5 minutes figuring out how to switch back to Yarn if that's what you want.

I do have an idea on a way we might be able to handle this a bit more gracefully but it would add a bunch of extra faff and I'm keen to get us being package manager agnostic by default so I'd rather go ahead with this and then later follow-up with the "graceful improvement" in a minor version if we do get feedback that highlights it worth the faff.

I will make it clearer here though that people should ensure packageManager is set as part of the upgrade

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not a fan of switching away from yarn as the default unless there's a good reason.

https://chat.openai.com/share/d33fe865-defd-41df-ac89-4db307a71052

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That AI conversation is not really useful because it doesn't have the full context - ultimately shakapacker itself shouldn't be setting a default as it's a library, and so npm is the default because that's the default in Node which is the default runtime shakapacker targets.

This change means effectively shakapacker aligns with node in terms of switching package managers so if you want to use yarn you just follow the recommended steps (i.e. corepack and packageManager) and both Node and shakapacker will respect that and just work 🙂

The only place we're selecting npm as an opinion is in the docs but that's because I don't think it's worth the overhead of documenting every possible combination of every package manager 🤷‍♂️


This enables support for package managers other than `yarn`, with `npm` being the default; to continue using Yarn,
specify it in `package.json` using the [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) property.

- Remove `yarn_install` rake task, and stop installing js packages automatically as part of `assets:precompile` [PR 412](https://github.com/shakacode/shakapacker/pull/412) by [G-Rath](https://github.com/g-rath).

- Remove `check_yarn` rake task [PR 443](https://github.com/shakacode/shakapacker/pull/443) by [G-Rath](https://github.com/g-rath).
Expand Down
118 changes: 73 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=
- [Optional support](#optional-support)
- [Installation](#installation)
- [Rails v6+](#rails-v6)
- [Using alternative package managers](#using-alternative-package-managers)
- [Note for Yarn v2 usage](#note-for-yarn-v2-usage)
- [Concepts](#concepts)
- [Usage](#usage)
- [Configuration and Code](#configuration-and-code)
Expand Down Expand Up @@ -101,13 +99,13 @@ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=
- Ruby 2.7+
- Rails 5.2+
- Node.js 14+
- Yarn

## Features
- Rails view helpers that fully support Webpack output, including HMR and code splitting.
- Convenient but not required webpack configuration. The only requirement is that your webpack configuration creates a manifest.
- HMR with the `shakapacker-dev-server`, such as for hot-reloading React!
- Automatic code splitting using multiple entry points to optimize JavaScript downloads.
- Support for [NPM](https://www.npmjs.com/package/npm), Yarn ([classic](https://classic.yarnpkg.com/lang/en/) and [berry](https://yarnpkg.com/getting-started)), [PNPM](https://pnpm.io/), and [Bun](https://bun.sh/)
G-Rath marked this conversation as resolved.
Show resolved Hide resolved
- [Webpack v5+](https://webpack.js.org/)
- ES6 with [babel](https://babeljs.io/), [SWC](https://swc.rs/), or [Esbuild](https://github.com/privatenumber/esbuild-loader)
- Asset compression, source-maps, and minification
Expand Down Expand Up @@ -147,40 +145,45 @@ Then run the following to install Shakapacker:

Before initiating the installation process, ensure you have committed all the changes. While installing Shakapacker, there might be some conflict between the existing file content and what Shakapacker tries to copy. You can either approve all the prompts for overriding these files or use the `FORCE=true` environment variable before the installation command to force the override without any prompt.

When `package.json` and/or `yarn.lock` changes, such as when pulling down changes to your local environment in team settings, be sure to keep your NPM packages up-to-date:
Shakapacker uses the [`package_json`](https://github.com/shakacode/package_json) gem to handle updating the `package.json` and interacting with the underlying package manager of choice for managing dependencies and running commands; the package manager is managed using the [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) property in the `package.json`, otherwise falling back to the value of `PACKAGE_JSON_FALLBACK_MANAGER` if set or otherwise `npm`.
G-Rath marked this conversation as resolved.
Show resolved Hide resolved

```bash
yarn
```

Note, in v6+, most JS packages are peer dependencies. Thus, the installer will add the packages:
If `packageManager` is not set when running `shakapacker:install`, Shakapacker will set it based on the lockfile and the result of calling `--version` on the inferred manager; if no lockfile is present, then `npm` be used unless you choose to explicitly set the `PACKAGE_JSON_FALLBACK_MANAGER` to your preferred package manager.

```bash
yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader \
compression-webpack-plugin terser-webpack-plugin \
webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
```

Previously, these "webpack" and "babel" packages were direct dependencies for `shakapacker`. By
making these peer dependencies, you have control over the versions used in your webpack and babel configs.

### Using alternative package managers

There is experimental support for using package managers besides Yarn classic for managing JavaScript dependencies using the [`package_json`](https://github.com/G-Rath/package_json) gem.

This can be enabled by setting the environment variable `SHAKAPACKER_USE_PACKAGE_JSON_GEM` to `true`; Shakapacker will then use the `package_json` gem which in turn will look for the [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) property in the `package.json` or otherwise the `PACKAGE_JSON_FALLBACK_MANAGER` environment variable to determine which manager to use, defaulting to `npm` if neither are found.
> **Note**
>
> The `packageManager` property is only used to determine the package manager to use, based primarily on its name.
> The version (if present) is only used to determine if Yarn Classic or Yarn Berry should be used, but is otherwise
> _not_ checked, nor is [`corepack`](https://nodejs.org/api/corepack.html) used to ensure that the package manager is installed.
>
> It is up to the developer to ensure that the desired package manager is actually install at the right version, which can be done
> using `corepack` or by other means.

See [here](https://github.com/G-Rath/package_json#specifying-a-package-manager) for a list of the supported package managers and more information; note that `package_json` does not handle ensuring the manager is installed.

> **Note**
>
> The rest of the documentation assumes that `package_json` is not being used, and so always references `yarn` - you should instead use the package manager of your choice for these commands.
> [NOTE]
>
> The rest of the documentation will only reference `npm` when providing commands such as to install optional packages except in cases where
> a particular package manager requires a very different command; otherwise it should be safe to just replace `npm` with the name of your
> preferred package manager when running the command

### Note for Yarn v2 usage
Note, in v6+, most JS packages are peer dependencies. Thus, the installer will add the packages:

If you are using Yarn v2 (berry), please note that PnP modules are not supported unless you're using `SHAKAPACKER_USE_PACKAGE_JSON_GEM`.
G-Rath marked this conversation as resolved.
Show resolved Hide resolved
- `@babel/core`
- `@babel/plugin-transform-runtime`
- `@babel/preset-env`
- `@babel/runtime`
- `babel-loader`
- `compression-webpack-plugin`
- `terser-webpack-plugin`
- `webpack`
- `webpack-assets-manifest`
- `webpack-cli`
- `webpack-merge`
- `webpack-sources`
- `webpack-dev-server`

To use Shakapacker with Yarn v2, make sure you set `nodeLinker: node-modules` in your `.yarnrc.yml` file as per the [Yarn docs](https://yarnpkg.com/getting-started/migration#step-by-step) to opt out of Plug'n'Play behavior.
Previously, these "webpack" and "babel" packages were direct dependencies for `shakapacker`. By
making these peer dependencies, you have control over the versions used in your webpack and babel configs.

## Concepts

Expand Down Expand Up @@ -621,13 +624,13 @@ See also [Customizing Babel Config](./docs/customizing_babel_config.md) for an e
#### TypeScript

```bash
yarn add typescript @babel/preset-typescript
npm install typescript @babel/preset-typescript
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@G-Rath @tomdracz why is the default switching from yarn to npm? That seems like a big change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@tomdracz tomdracz Mar 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked briefly with @justin808 and in two minds about this default. I hear the point around matching node default (since you will always get at least NPM), but think Rails has mostly set on using yarn and requires bit of extra work to get other package managers working.

How hard would it be to retain yarn default? Is adding pkg manager into package.json something we could automate? Some existing tool detection akin to https://github.com/rails/jsbundling-rails/blob/main/lib/tasks/jsbundling/build.rake?

As said elsewhere, switching manager after install shouldn't be a rocked science so not opposed to new default in principle, but given the ecosystem, I wonder if we can make upgrade less annoying (those 5 mins switching back to yarn and having package-lock.json when I've had yarn before WILL annoy me 😅) or find some other compromise?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't find a good compromise path though, I would say that IMO benefits of choice of pkg manager outweigh the pain of switching

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails has mostly set on using yarn and requires bit of extra work to get other package managers working.

From what I've seen that was covered by Webpacker which is now Shakapacker, and so because that now supports multiple package managers there is no "bit of extra work" required (beyond setting up the package manager of choice, which isn't our cost to pay) - it's literally set the packageManager property and it just works (I've already done this for a few apps at Ackama which are using NPM in production).

The thing that makes it tricky is packageManager requires an exact version and Yarn has two version different versions in v1 (classic) and v2+ (berry) so ironically it's the hardest package manager to guess for.

The reason why jsbundling can get away with such a simple check is because it purposely tries to interact with Node as little as possible whereas Shakapacker has a much smarter integration that requires it to understand more about the package manager its using e.g. to pass in commands.

I wonder if we can make upgrade less annoying

This is imo the hardest thing to address because unlike install users could just not follow the upgrade path and run into this all over the place so we'd have to stick a check or guard around pretty much every method and have that be there for the whole of v8.

It might be ok though 🤔

This has also inspired me to have another look at the install logic, as I think we can probably do better about setting packageJson.

```

Babel won’t perform any type-checking on TypeScript code. To optionally use type-checking run:

```bash
yarn add fork-ts-checker-webpack-plugin
npm install fork-ts-checker-webpack-plugin
```

Add tsconfig.json
Expand Down Expand Up @@ -668,7 +671,7 @@ module.exports = generateWebpackConfig({
To enable CSS support in your application, add the following packages:

```bash
yarn add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
npm install css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
```

Optionally, add the `CSS` extension to webpack config for easy resolution.
Expand All @@ -692,18 +695,18 @@ then add the relevant pre-processors:
#### Postcss

```bash
yarn add postcss postcss-loader
npm install postcss postcss-loader
```

Optionally add these two plugins if they are required in your `postcss.config.js`:
```bash
yarn add postcss-preset-env postcss-flexbugs-fixes
npm install postcss-preset-env postcss-flexbugs-fixes
```

#### Sass

```bash
yarn add sass-loader
npm install sass-loader
```

You will also need to install [Dart Sass](https://github.com/sass/dart-sass), [Node Sass](https://github.com/sass/node-sass) or [Sass Embedded](https://github.com/sass/embedded-host-node) to pick the implementation to use. sass-loader will automatically pick an implementation based on installed packages.
Expand All @@ -712,35 +715,35 @@ Please refer to [sass-loader documentation](https://www.npmjs.com/package/sass-l

##### Dart Sass
```bash
yarn add sass
npm install sass
```

##### Node Sass
```bash
yarn add node-sass
npm install node-sass
```

##### Sass Embedded
```bash
yarn add sass-embedded
npm install sass-embedded
```

#### Less

```bash
yarn add less less-loader
npm install less less-loader
```

#### Stylus

```bash
yarn add stylus stylus-loader
npm install stylus stylus-loader
```

#### CoffeeScript

```bash
yarn add coffeescript coffee-loader
npm install coffeescript coffee-loader
```

#### Other frameworks
Expand Down Expand Up @@ -840,16 +843,24 @@ bundle update shakapacker
# overwrite your changes to the default install files and revert any unwanted changes from the install
rails shakapacker:install

# yarn 1 instructions
# using npm
npm install shakapacker@latest
npm install webpack-dev-server@latest

# using yarn classic
yarn upgrade shakapacker --latest
yarn upgrade webpack-dev-server --latest

# yarn 2 instructions
# using yarn berry
yarn up shakapacker@latest
yarn up webpack-dev-server@latest

# using pnpm
pnpm up shakapacker@latest
pnpm up webpack-dev-server@latest

# Or to install the latest release (including pre-releases)
yarn add shakapacker@next
npm install shakapacker@next
Comment on lines -852 to +863
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The next tag on npmjs refers to v6.0.0-rc.14.
I'm not sure why it is so, but that is not what we want to use here.

Though not related to this PR, it is worth it to review it again.

CC: @justin808

```

Also, consult the [CHANGELOG](./CHANGELOG.md) for additional upgrade links.
Expand Down Expand Up @@ -916,7 +927,24 @@ Shakapacker hooks up a new `shakapacker:compile` task to `assets:precompile`, wh

This behavior is optional & can be disabled by either setting a `SHAKAPACKER_PRECOMPILE` environment variable to `false`, `no`, `n`, or `f`, or by setting a `shakapacker_precompile` key in your `shakapacker.yml` to `false`. ([source code](./lib/shakapacker/configuration.rb#L34))

When compiling assets for production on a remote server, such as a continuous integration environment, it's recommended to use `yarn install --frozen-lockfile` to install NPM packages on the remote host to ensure that the installed packages match the `yarn.lock` file.
When compiling assets for production on a remote server, such as a continuous integration environment, it's recommended to ensure the exact versions specified in your lockfile are installed:

```
# using npm
npm ci

# using yarn classic
yarn install --frozen-lockfile

# using yarn berry
yarn install --immutable

# using pnpm
pnpm install --frozen-lockfile

# using bun
bun install --frozen-lockfile
```

If you are using a CDN setup, Shakapacker does NOT use the `ASSET_HOST` environment variable to prefix URLs for assets during bundle compilation. You must use the `SHAKAPACKER_ASSET_HOST` environment variable instead (`WEBPACKER_ASSET_HOST` if you're using any version of Webpacker or Shakapacker before Shakapacker v7).

Expand Down
4 changes: 2 additions & 2 deletions docs/customizing_babel_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ This example shows how you can create an object and apply _additional_ presets a
To use this example file,

```
yarn add react react-dom @babel/preset-react
yarn add --dev @pmmmwh/react-refresh-webpack-plugin react-refresh
npm install react react-dom @babel/preset-react
npm install --dev @pmmmwh/react-refresh-webpack-plugin react-refresh
```

```js
Expand Down
19 changes: 13 additions & 6 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ We're essentially doing the following here:
* Adding the Heroku NodeJS and Ruby buildpacks for your app. This allows the `npm` or `yarn` executables to properly function when compiling your app - as well as Ruby.
* Pushing your code to Heroku and kicking off the deployment

Your production build process is responsible for running `yarn install` before `rake assets:precompile`. For example, if you are on Heroku, the `heroku/nodejs` buildpack must run **prior** to the `heroku/ruby` buildpack for precompilation to run successfully.
Your production build process is responsible for installing your JavaScript dependencies before `rake assets:precompile`. For example, if you are on Heroku, the `heroku/nodejs` buildpack must run **prior** to the `heroku/ruby` buildpack for precompilation to run successfully.

## Nginx

Expand Down Expand Up @@ -100,18 +100,25 @@ Make sure you have your public output path (default `public/packs`), the shakapa
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "tmp/shakapacker", "public/packs", ".bundle", "node_modules"
```

If you have `node_modules` added to `:linked_dirs` you'll need to run yarn install before `deploy:assets:precompile`, so you can add this code snippet at the bottom deploy.rb
If you have `node_modules` added to `:linked_dirs` you'll need to install your JavaScript dependencies before `deploy:assets:precompile`; you can use `package_json` to do this generically:

```ruby
before "deploy:assets:precompile", "deploy:yarn_install"
before "deploy:assets:precompile", "deploy:js_install"
namespace :deploy do
desc "Run rake yarn install"
task :yarn_install do
desc "Run rake js install"
task :js_install do
require "package_json"

# this will use the package manager specified via `packageManager`, or otherwise fallback to `npm`
native_js_install_command = PackageJson.read.manager.native_install_command(frozen: true).join(" ")

on roles(:web) do
within release_path do
execute("cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")
execute("cd #{release_path} && #{native_js_install_command}")
end
end
end
end
```

You can also replace the use of `package_json` with the underlying native install command for your preferred package manager.
18 changes: 6 additions & 12 deletions docs/react.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

These steps describe creating a Rails/React app, using Shakapacker as the bundler.

Before starting, ensure that you have Yarn installed, for example:

```shell
npm i -g yarn
```

## Easy Setup
If you'd like easy integration of React with Ruby on Rails, see [React on Rails](https://github.com/shakacode/react_on_rails).

Expand All @@ -24,8 +18,8 @@ Create a new Rails app as per the [installation instructions in the README](http
Add React, as well as the necessary libraries to enable CSS support in your application:

```shell
yarn add react react-dom @babel/preset-react
yarn add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
npm install react react-dom @babel/preset-react
npm install css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
```

Update the Babel configuration in the `package.json` file:
Expand All @@ -52,7 +46,7 @@ In `config/shakapacker.yml` set `hmr` is set to `true`.
Install the [react-refresh](https://www.npmjs.com/package/react-refresh) package, as well as [@pmmmwh/react-refresh-webpack-plugin](https://www.npmjs.com/package/@pmmmwh/react-refresh-webpack-plugin):

```shell
yarn add --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
npm install --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
```

Alter `config/webpack/webpack.config.js` like so:
Expand Down Expand Up @@ -142,8 +136,8 @@ cd myapp
bundle add shakapacker --strict
./bin/bundle install
./bin/rails shakapacker:install
yarn add react react-dom @babel/preset-react
yarn add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
npm install react react-dom @babel/preset-react
npm install css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
```

2. Generate a controller
Expand Down Expand Up @@ -192,7 +186,7 @@ hmr: true
8. Install the [react-refresh](https://www.npmjs.com/package/react-refresh) package, as well as [@pmmmwh/react-refresh-webpack-plugin](https://www.npmjs.com/package/@pmmmwh/react-refresh-webpack-plugin):

```shell
yarn add --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
npm install --dev react-refresh @pmmmwh/react-refresh-webpack-plugin
```

9. Alter `config/webpack/webpack.config.js` like so:
Expand Down
Loading
Loading