shakapacker 10.0.0 → 10.1.0.rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -1
- data/README.md +23 -14
- data/lib/install/package.json +2 -2
- data/lib/shakapacker/compiler.rb +29 -0
- data/lib/shakapacker/doctor.rb +325 -13
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +24 -3
- data/shakapacker.gemspec +2 -6
- metadata +3 -269
- data/.claude/commands/address-review.md +0 -234
- data/.claude/commands/update-changelog.md +0 -354
- data/.claude/commands/verify.md +0 -12
- data/.claude/rules/coding-style.md +0 -7
- data/.claude/rules/git-workflow.md +0 -6
- data/.claude/rules/open-source.md +0 -7
- data/.claude/rules/testing.md +0 -9
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -21
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -21
- data/.github/STATUS.md +0 -1
- data/.github/actionlint-matcher.json +0 -17
- data/.github/workflows/claude-code-review.yml +0 -45
- data/.github/workflows/claude.yml +0 -55
- data/.github/workflows/dummy.yml +0 -48
- data/.github/workflows/eslint-validation.yml +0 -46
- data/.github/workflows/generator.yml +0 -86
- data/.github/workflows/node.yml +0 -171
- data/.github/workflows/ruby.yml +0 -132
- data/.github/workflows/test-bundlers.yml +0 -183
- data/.github/workflows/trigger-docs-site.yml +0 -24
- data/.gitignore +0 -46
- data/.husky/pre-commit +0 -2
- data/.node-version +0 -1
- data/.npmignore +0 -56
- data/.prettierignore +0 -8
- data/.rspec +0 -1
- data/.rubocop.yml +0 -231
- data/.yalcignore +0 -26
- data/CLAUDE.md +0 -74
- data/CONTRIBUTING.md +0 -379
- data/ESLINT_TECHNICAL_DEBT.md +0 -165
- data/Gemfile +0 -5
- data/Gemfile.development_dependencies +0 -15
- data/Rakefile +0 -88
- data/TODO.md +0 -58
- data/TODO_v9.md +0 -97
- data/__mocks__/nonexistent/package.json +0 -4
- data/__mocks__/sass-loader/package.json +0 -4
- data/bin/conductor-exec +0 -24
- data/bin/diff-bundler-config +0 -64
- data/bin/setup +0 -36
- data/bin/shakapacker-config +0 -11
- data/conductor-setup.sh +0 -147
- data/conductor.json +0 -9
- data/config/README.md +0 -3
- data/config/shakapacker.yml +0 -1
- data/docs/api-reference.md +0 -497
- data/docs/cdn_setup.md +0 -384
- data/docs/common-upgrades.md +0 -695
- data/docs/config-diff.md +0 -159
- data/docs/configuration.md +0 -845
- data/docs/css-modules-export-mode.md +0 -525
- data/docs/customizing_babel_config.md +0 -89
- data/docs/deployment.md +0 -195
- data/docs/developing_shakapacker.md +0 -35
- data/docs/early_hints.md +0 -433
- data/docs/early_hints_manual_api.md +0 -454
- data/docs/feature_testing.md +0 -492
- data/docs/node_package_api.md +0 -70
- data/docs/optional-peer-dependencies.md +0 -205
- data/docs/peer-dependencies.md +0 -77
- data/docs/precompile_hook.md +0 -487
- data/docs/preventing_fouc.md +0 -132
- data/docs/react.md +0 -83
- data/docs/releasing.md +0 -293
- data/docs/rspack.md +0 -218
- data/docs/rspack_migration_guide.md +0 -849
- data/docs/sprockets.md +0 -11
- data/docs/style_loader_vs_mini_css.md +0 -48
- data/docs/subresource_integrity.md +0 -60
- data/docs/transpiler-migration.md +0 -212
- data/docs/transpiler-performance.md +0 -200
- data/docs/troubleshooting.md +0 -521
- data/docs/typescript-migration.md +0 -388
- data/docs/typescript.md +0 -103
- data/docs/using_esbuild_loader.md +0 -128
- data/docs/using_swc_loader.md +0 -258
- data/docs/v6_upgrade.md +0 -195
- data/docs/v7_upgrade.md +0 -61
- data/docs/v8_upgrade.md +0 -193
- data/docs/v9_upgrade.md +0 -618
- data/eslint.config.fast.js +0 -254
- data/eslint.config.js +0 -309
- data/gemfiles/Gemfile-rails-edge +0 -12
- data/gemfiles/Gemfile-rails.6.0.x +0 -10
- data/gemfiles/Gemfile-rails.6.1.x +0 -12
- data/gemfiles/Gemfile-rails.7.0.x +0 -12
- data/gemfiles/Gemfile-rails.7.1.x +0 -11
- data/gemfiles/Gemfile-rails.7.2.x +0 -11
- data/gemfiles/Gemfile-rails.8.0.x +0 -11
- data/jest.config.js +0 -12
- data/knip.ts +0 -69
- data/package/.npmignore +0 -4
- data/package/babel/preset.ts +0 -59
- data/package/config.ts +0 -189
- data/package/configExporter/buildValidator.ts +0 -906
- data/package/configExporter/cli.ts +0 -1748
- data/package/configExporter/configDocs.ts +0 -102
- data/package/configExporter/configFile.ts +0 -663
- data/package/configExporter/fileWriter.ts +0 -112
- data/package/configExporter/index.ts +0 -15
- data/package/configExporter/types.ts +0 -159
- data/package/configExporter/yamlSerializer.ts +0 -391
- data/package/dev_server.ts +0 -27
- data/package/env.ts +0 -92
- data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +0 -36
- data/package/environments/base.ts +0 -147
- data/package/environments/development.ts +0 -88
- data/package/environments/production.ts +0 -82
- data/package/environments/test.ts +0 -55
- data/package/environments/types.ts +0 -98
- data/package/esbuild/index.ts +0 -40
- data/package/index.d.ts +0 -72
- data/package/index.d.ts.template +0 -72
- data/package/index.ts +0 -104
- data/package/loaders.d.ts +0 -28
- data/package/optimization/rspack.ts +0 -36
- data/package/optimization/webpack.ts +0 -55
- data/package/plugins/envFilter.ts +0 -82
- data/package/plugins/rspack.ts +0 -119
- data/package/plugins/webpack.ts +0 -82
- data/package/rspack/index.ts +0 -91
- data/package/rules/babel.ts +0 -19
- data/package/rules/coffee.ts +0 -6
- data/package/rules/css.ts +0 -3
- data/package/rules/erb.ts +0 -21
- data/package/rules/esbuild.ts +0 -10
- data/package/rules/file.ts +0 -41
- data/package/rules/jscommon.ts +0 -27
- data/package/rules/less.ts +0 -22
- data/package/rules/raw.ts +0 -28
- data/package/rules/rspack.ts +0 -174
- data/package/rules/sass.ts +0 -21
- data/package/rules/stylus.ts +0 -22
- data/package/rules/swc.ts +0 -10
- data/package/rules/webpack.ts +0 -15
- data/package/swc/index.ts +0 -54
- data/package/types/README.md +0 -90
- data/package/types/index.ts +0 -69
- data/package/types.ts +0 -105
- data/package/utils/bundlerUtils.ts +0 -232
- data/package/utils/configPath.ts +0 -6
- data/package/utils/debug.ts +0 -45
- data/package/utils/defaultConfigPath.ts +0 -7
- data/package/utils/ensureManifestExists.ts +0 -17
- data/package/utils/errorCodes.ts +0 -249
- data/package/utils/errorHelpers.ts +0 -152
- data/package/utils/getStyleRule.ts +0 -75
- data/package/utils/helpers.ts +0 -99
- data/package/utils/inliningCss.ts +0 -8
- data/package/utils/pathValidation.ts +0 -207
- data/package/utils/requireOrError.ts +0 -24
- data/package/utils/snakeToCamelCase.ts +0 -5
- data/package/utils/typeGuards.ts +0 -388
- data/package/utils/validateDependencies.ts +0 -61
- data/package/webpack-types.d.ts +0 -33
- data/package/webpackDevServerConfig.ts +0 -151
- data/package.json +0 -228
- data/prettier.config.js +0 -4
- data/scripts/remove-use-strict.js +0 -44
- data/scripts/type-check-no-emit.js +0 -27
- data/test/configExporter/buildValidator.test.js +0 -1295
- data/test/configExporter/configFile.test.js +0 -393
- data/test/configExporter/integration.test.js +0 -262
- data/test/helpers.js +0 -67
- data/test/package/bundlerUtils.rspack.test.js +0 -149
- data/test/package/bundlerUtils.test.js +0 -97
- data/test/package/config.test.js +0 -111
- data/test/package/configExporter/cli.test.js +0 -440
- data/test/package/configExporter/types.test.js +0 -163
- data/test/package/configExporter.test.js +0 -491
- data/test/package/dev_server.test.js +0 -44
- data/test/package/development.test.js +0 -52
- data/test/package/env.test.js +0 -92
- data/test/package/environments/base.test.js +0 -124
- data/test/package/environments/development.test.js +0 -59
- data/test/package/environments/production.test.js +0 -115
- data/test/package/helpers.test.js +0 -11
- data/test/package/index.test.js +0 -54
- data/test/package/plugins/envFiltering.test.js +0 -453
- data/test/package/plugins/webpackSubresourceIntegrity.test.js +0 -89
- data/test/package/production.test.js +0 -41
- data/test/package/rspack/index.test.js +0 -293
- data/test/package/rspack/optimization.test.js +0 -86
- data/test/package/rspack/plugins.test.js +0 -185
- data/test/package/rspack/rules.test.js +0 -229
- data/test/package/rules/babel.test.js +0 -85
- data/test/package/rules/esbuild.test.js +0 -68
- data/test/package/rules/file.test.js +0 -87
- data/test/package/rules/raw.test.js +0 -45
- data/test/package/rules/sass-version-parsing.test.js +0 -71
- data/test/package/rules/sass.test.js +0 -28
- data/test/package/rules/sass1.test.js +0 -26
- data/test/package/rules/sass16.test.js +0 -24
- data/test/package/rules/swc.test.js +0 -70
- data/test/package/rules/webpack.test.js +0 -35
- data/test/package/staging.test.js +0 -41
- data/test/package/test.test.js +0 -37
- data/test/package/transpiler-defaults.test.js +0 -169
- data/test/package/utils/ensureManifestExists.test.js +0 -51
- data/test/package/webpackDevServerConfig.test.js +0 -55
- data/test/package/yamlSerializer.test.js +0 -204
- data/test/peer-dependencies.sh +0 -85
- data/test/resolver.js +0 -44
- data/test/scripts/remove-use-strict.test.js +0 -125
- data/test/typescript/build.test.js +0 -118
- data/test/typescript/environments.test.js +0 -107
- data/test/typescript/pathValidation.test.js +0 -186
- data/test/typescript/requireOrError.test.js +0 -49
- data/test/typescript/securityValidation.test.js +0 -182
- data/tools/README.md +0 -134
- data/tools/css-modules-v9-codemod.js +0 -179
- data/tsconfig.eslint.json +0 -9
- data/tsconfig.json +0 -38
- data/yarn.lock +0 -6806
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 632a8c1773b8b7168ac13d0b0675e886c3d1359635ddd695b32e12218748708c
|
|
4
|
+
data.tar.gz: 8dcd25b6593ff26d8b277c01c54a1df970e69ced4166a5a918c9123fc04bdea1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 461f192f52757479deb8251b434b34b7c1839f923ae02725917f85ba96b47e1a1f9d45cc1dabf989f9fa33156dbcfa479d613143f2f2e0b95152a589be9bb852
|
|
7
|
+
data.tar.gz: a6070c988e4a317f91210f642eb25471fc2827c67e7cdad659a0c040839c0cd2c3adb1b9293eceb17a7586fd2128c4d46a776a8b387f5322bd53a348ec5ece82
|
data/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,41 @@
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [v10.1.0-rc.0] - May 20, 2026
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Added supplemental npm packages `shakapacker-webpack` and `shakapacker-rspack`**. [PR #1096](https://github.com/shakacode/shakapacker/pull/1096) by [justin808](https://github.com/justin808). Optional packages that lockstep with core and bundle the managed-build stack as direct `dependencies` (so a single `yarn add shakapacker-webpack` pulls in `shakapacker`, `webpack`, `webpack-cli`, and `webpack-assets-manifest`; the rspack package bundles `shakapacker`, `@rspack/core`, `@rspack/cli`, and `rspack-manifest-plugin`). Optional features (transpilers, dev-server, CSS preprocessors, react-refresh) remain as opt-in `peerDependencies` so SCSS/native-binding bloat isn't forced on every install. The wrappers emit structured warnings (`SHAKAPACKER_BUNDLER_MISMATCH`, `SHAKAPACKER_NO_TRANSPILER`) when `config.assets_bundler` or `javascript_transpiler` doesn't match the installed peers. See the [v10.1 migration guide](docs/migration/v10.1-supplemental-packages.md) for adoption steps and [`docs/dependency-strategy.md`](docs/dependency-strategy.md) for the design rationale and v11 roadmap.
|
|
17
|
+
- **Added `shakapacker:doctor` check for disabled Rspack cache**. [PR #1100](https://github.com/shakacode/shakapacker/pull/1100) by [justin808](https://github.com/justin808). The doctor now inspects the Rspack config file for an explicit `cache: false`, warns when found (disabling cache causes significantly slower builds), and also flags Rspack v1 installs (where persistent cache is experimental) with a recommendation to upgrade to v2.
|
|
18
|
+
- **Added a `shakapacker:doctor` hint to compiler output**. [PR #1100](https://github.com/shakacode/shakapacker/pull/1100) by [justin808](https://github.com/justin808). The compiler now logs a one-time tip suggesting `bundle exec rake shakapacker:doctor` after a failed compilation, so healthy build loops stay quiet.
|
|
19
|
+
|
|
20
|
+
### Migration Notes
|
|
21
|
+
|
|
22
|
+
- **Simplify your `package.json` by adopting a supplemental package**. Existing apps can drop the explicit managed-build deps from `devDependencies` and rely on the bundled stack:
|
|
23
|
+
- **Rspack apps** can replace `shakapacker` + `@rspack/core` + `@rspack/cli` + `rspack-manifest-plugin` with a single `shakapacker-rspack`. See `packages/shakapacker-rspack/README.md` §"Simplifying an existing rspack install" for the before/after.
|
|
24
|
+
- **Webpack apps** can replace `shakapacker` + `webpack` + `webpack-cli` + `webpack-assets-manifest` with a single `shakapacker-webpack`. See `packages/shakapacker-webpack/README.md` §"Simplifying an existing webpack install" for the before/after.
|
|
25
|
+
- Optional peers (transpilers, `webpack-dev-server`, CSS preprocessors, react-refresh) stay only if your app uses those features.
|
|
26
|
+
- Adoption is opt-in: leaving your `package.json` untouched on v10.1 also continues to work.
|
|
27
|
+
|
|
28
|
+
- **Adopting `shakapacker-webpack` requires `webpack-assets-manifest@^6.0.0`**. Core `shakapacker` still accepts both v5 and v6 (`^5.0.6 || ^6.0.0`), but `shakapacker-webpack` pins `~6.5.1`. Apps still on `webpack-assets-manifest@5.x` must upgrade when switching to the supplemental package; v6 fixed an ENOENT crash on clean builds with `merge: true` and dropped a Node 14 install path. See [the v5→v6 release notes](https://github.com/webdeveric/webpack-assets-manifest/releases) and `packages/shakapacker-webpack/README.md` for details.
|
|
29
|
+
|
|
30
|
+
### ⚠️ Breaking Changes
|
|
31
|
+
|
|
32
|
+
- **Breaking: tightened `package.json` `engines.node` to `^20.19.0 || >=22.12.0`**. [PR #1099](https://github.com/shakacode/shakapacker/pull/1099) by [justin808](https://github.com/justin808). Raised from `>= 20`, dropping support for Node 20.0.0–20.18.x and Node 21.x to match `@rspack/core@2.0.0-rc.0`. Consumers on those versions will hit an engine error with `--engine-strict` or yarn workspaces and need to upgrade. The PR also bumps `.node-version` to `22.20.0` and updates `conductor-setup.sh` to enforce the same disjoint range up front, so contributors get a clear error before `yarn install` fails with a confusing engine mismatch.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Changed `shakapacker:install` to default fresh Rspack installs to v2 (`^2.0.0-0`)**. [PR #1091](https://github.com/shakacode/shakapacker/pull/1091) by [ihabadham](https://github.com/ihabadham). `lib/install/package.json` now declares `@rspack/core` and `@rspack/cli` as `^1.0.0 || ^2.0.0-0`; fresh installs pick the v2 range. Existing apps are unaffected. Note: Rspack v2 requires Node.js 20.19.0+.
|
|
37
|
+
- **Slimmed the published gem from ~486K (294 files) to ~121K (75 files)**. [PR #1110](https://github.com/shakacode/shakapacker/pull/1110) by [justin808](https://github.com/justin808). Replaced the broad `git ls-files` gem manifest with an explicit runtime/install allowlist (`CHANGELOG.md`, `MIT-LICENSE`, `README.md`, gemspec, `lib`, `sig`), excluding repo-only docs, tests, JavaScript package source, CI/tooling files, and `test_files` metadata from the published gem. Fixes [#987](https://github.com/shakacode/shakapacker/issues/987).
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **Fixed Rspack React Refresh plugin loading with `@rspack/plugin-react-refresh` v2**. [PR #1116](https://github.com/shakacode/shakapacker/pull/1116) by [justin808](https://github.com/justin808). Shakapacker now reads the v2 named `ReactRefreshRspackPlugin` export while retaining compatibility with v1 direct/default CommonJS export shapes, preventing `TypeError: ReactRefreshRspackPlugin is not a constructor` during rspack dev-server startup.
|
|
42
|
+
- **Widened `@rspack/plugin-react-refresh` peer range to `^1.0.0 || ^2.0.0-0`**. [PR #1091](https://github.com/shakacode/shakapacker/pull/1091) by [ihabadham](https://github.com/ihabadham). Fixes the `ERESOLVE` conflict when installing `@rspack/plugin-react-refresh@^2.0.0` alongside `shakapacker@10.0.0`.
|
|
43
|
+
- **Fixed `NodePackageVersion#find_version` for local-path `shakapacker` installs (e.g. `yalc`, `file:`, relative paths)**. [PR #1086](https://github.com/shakacode/shakapacker/pull/1086) by [justin808](https://github.com/justin808). The version check now consults `package.json` first and short-circuits on `../` or `file:` dependencies, so stale lockfile semvers no longer trigger false gem↔node version mismatches. `package_json_dependency` also consults `devDependencies` in addition to `dependencies`. The `LOCAL_PATH_REGEX` constant replaces a duplicated inline regex and anchors both alternatives to the start of the string, removing a latent false-positive on version strings containing `..` mid-value.
|
|
44
|
+
- **Detected single-dot (`./...`) local-path declarations in `NodePackageVersion#find_version`**. [PR #1106](https://github.com/shakacode/shakapacker/pull/1106) by [justin808](https://github.com/justin808). Extended `LOCAL_PATH_REGEX` to treat `./vendor/shakapacker`-style declarations as local-path installs (alongside the `../` and `file:` patterns added in [#1086](https://github.com/shakacode/shakapacker/pull/1086)), so version checks short-circuit before consulting potentially stale lockfile semvers. Fixes [#1103](https://github.com/shakacode/shakapacker/issues/1103).
|
|
45
|
+
- **Fix rspack setup not reusing certain shared webpack-rspack config settings**. [PR #1085](https://github.com/shakacode/shakapacker/pull/1085) by [brunodccarvalho](https://github.com/brunodccarvalho). Default config changes include `optimization.splitChunks.chunks="all"`, `optimization.runtimeChunk="single"`, the webpack compression plugin in production, and the removal of minimization plugins in development. Fixes [#984](https://github.com/shakacode/shakapacker/issues/984).
|
|
46
|
+
|
|
12
47
|
## [v10.0.0] - April 8, 2026
|
|
13
48
|
|
|
14
49
|
### Added
|
|
@@ -909,7 +944,8 @@ Note: [Rubygem is 6.3.0.pre.rc.1](https://rubygems.org/gems/shakapacker/versions
|
|
|
909
944
|
|
|
910
945
|
See [CHANGELOG.md in rails/webpacker (up to v5.4.3)](https://github.com/rails/webpacker/blob/master/CHANGELOG.md)
|
|
911
946
|
|
|
912
|
-
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.0.0...main
|
|
947
|
+
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.1.0-rc.0...main
|
|
948
|
+
[v10.1.0-rc.0]: https://github.com/shakacode/shakapacker/compare/v10.0.0...v10.1.0-rc.0
|
|
913
949
|
[v10.0.0]: https://github.com/shakacode/shakapacker/compare/v9.7.0...v10.0.0
|
|
914
950
|
[v9.7.0]: https://github.com/shakacode/shakapacker/compare/v9.6.1...v9.7.0
|
|
915
951
|
[v9.6.1]: https://github.com/shakacode/shakapacker/compare/v9.6.0...v9.6.1
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Shakapacker (
|
|
1
|
+
# Shakapacker (v10)
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
_🚀 Shakapacker
|
|
5
|
+
_🚀 Shakapacker 10 supports [Rspack](https://rspack.rs/) — up to 17x faster than webpack per [upstream benchmarks](./docs/transpiler-performance.md#published-benchmarks)!_
|
|
6
6
|
|
|
7
7
|
_📖 **Full documentation at [shakapacker.com](https://shakapacker.com)**_
|
|
8
8
|
|
|
@@ -11,7 +11,8 @@ _📖 **Full documentation at [shakapacker.com](https://shakapacker.com)**_
|
|
|
11
11
|
_Official, actively maintained successor to [rails/webpacker](https://github.com/rails/webpacker). ShakaCode stands behind the long-term maintenance and development of this project for the Rails community._
|
|
12
12
|
|
|
13
13
|
- ⚠️ See the [6-stable](https://github.com/shakacode/shakapacker/tree/6-stable) branch for Shakapacker v6.x code and documentation. :warning:
|
|
14
|
-
- **See [
|
|
14
|
+
- **See the [v10.0.0 release notes](https://github.com/shakacode/shakapacker/releases/tag/v10.0.0) for upgrading from v9 to v10.**
|
|
15
|
+
- **See [V9 Upgrade](./docs/v9_upgrade.md) for upgrading from v8 to v9.**
|
|
15
16
|
- See [V8 Upgrade](./docs/v8_upgrade.md) for upgrading from the v7 release.
|
|
16
17
|
- See [V7 Upgrade](./docs/v7_upgrade.md) for upgrading from the v6 release.
|
|
17
18
|
- See [V6 Upgrade](./docs/v6_upgrade.md) for upgrading from v5 or prior v6 releases.
|
|
@@ -21,7 +22,7 @@ _Official, actively maintained successor to [rails/webpacker](https://github.com
|
|
|
21
22
|
[](https://github.com/shakacode/shakapacker/actions)
|
|
22
23
|
[](https://github.com/shakacode/shakapacker/actions)
|
|
23
24
|
|
|
24
|
-
[](https://www.npmjs.com/package/shakapacker)
|
|
25
26
|
[](https://rubygems.org/gems/shakapacker)
|
|
26
27
|
[](https://badge.fury.io/js/shakapacker)
|
|
27
28
|
|
|
@@ -133,7 +134,7 @@ Here's a testimonial from Jon Rajavuori of [Academia.edu](https://www.academia.e
|
|
|
133
134
|
|
|
134
135
|
- Ruby 2.7+
|
|
135
136
|
- Rails 5.2+
|
|
136
|
-
- Node.js 20
|
|
137
|
+
- Node.js `^20.19.0` or `>=22.12.0`
|
|
137
138
|
|
|
138
139
|
## Features
|
|
139
140
|
|
|
@@ -159,6 +160,8 @@ _Requires extra packages to be installed._
|
|
|
159
160
|
|
|
160
161
|
## Installation
|
|
161
162
|
|
|
163
|
+
See the [Installation guide](./docs/installation.md) for a step-by-step walkthrough.
|
|
164
|
+
|
|
162
165
|
### Rails v6+
|
|
163
166
|
|
|
164
167
|
With Rails v6+, skip JavaScript for a new app and follow below Manual Installation Steps to manually add the `shakapacker` gem to your Gemfile.
|
|
@@ -238,7 +241,7 @@ Depending on your setup, you'll need different subsets of the optional peer depe
|
|
|
238
241
|
```json
|
|
239
242
|
{
|
|
240
243
|
"dependencies": {
|
|
241
|
-
"shakapacker": "^
|
|
244
|
+
"shakapacker": "^10.0.0",
|
|
242
245
|
"@babel/core": "^7.17.9",
|
|
243
246
|
"@babel/plugin-transform-runtime": "^7.17.0",
|
|
244
247
|
"@babel/preset-env": "^7.16.11",
|
|
@@ -261,7 +264,7 @@ Depending on your setup, you'll need different subsets of the optional peer depe
|
|
|
261
264
|
```json
|
|
262
265
|
{
|
|
263
266
|
"dependencies": {
|
|
264
|
-
"shakapacker": "^
|
|
267
|
+
"shakapacker": "^10.0.0",
|
|
265
268
|
"@swc/core": "^1.3.0",
|
|
266
269
|
"swc-loader": "^0.2.0",
|
|
267
270
|
"compression-webpack-plugin": "^9.0.0",
|
|
@@ -274,14 +277,14 @@ Depending on your setup, you'll need different subsets of the optional peer depe
|
|
|
274
277
|
}
|
|
275
278
|
```
|
|
276
279
|
|
|
277
|
-
**For Rspack + SWC (
|
|
280
|
+
**For Rspack + SWC (largest end-to-end speedup — see [transpiler-performance guide](./docs/transpiler-performance.md#published-benchmarks)):**
|
|
278
281
|
|
|
279
282
|
```json
|
|
280
283
|
{
|
|
281
284
|
"dependencies": {
|
|
282
|
-
"shakapacker": "^
|
|
283
|
-
"@rspack/core": "^
|
|
284
|
-
"@rspack/cli": "^
|
|
285
|
+
"shakapacker": "^10.0.0",
|
|
286
|
+
"@rspack/core": "^2.0.0-0",
|
|
287
|
+
"@rspack/cli": "^2.0.0-0",
|
|
285
288
|
"@swc/core": "^1.3.0",
|
|
286
289
|
"swc-loader": "^0.2.0",
|
|
287
290
|
"rspack-manifest-plugin": "^5.0.0"
|
|
@@ -923,7 +926,7 @@ You can also change your Babel configuration by removing these lines in your `pa
|
|
|
923
926
|
|
|
924
927
|
### SWC configuration
|
|
925
928
|
|
|
926
|
-
SWC is the recommended JavaScript transpiler in Shakapacker v9
|
|
929
|
+
SWC is the recommended JavaScript transpiler in Shakapacker v10 (this default was introduced in v9). SWC's own benchmark reports being [20x faster than Babel on a single thread and 70x faster on four cores](https://swc.rs/); end-to-end Shakapacker speedups are typically smaller but still substantial. New installations use SWC by default via the installation template. You can read more at [SWC usage docs](./docs/using_swc_loader.md).
|
|
927
930
|
|
|
928
931
|
**Note on defaults**: The installation template explicitly sets `javascript_transpiler: "swc"` for new projects. However, for backward compatibility, webpack's runtime default (when no explicit config exists) remains `"babel"`. Rspack always defaults to `"swc"`.
|
|
929
932
|
|
|
@@ -1272,13 +1275,19 @@ npm install shakapacker@next
|
|
|
1272
1275
|
|
|
1273
1276
|
Also, consult the [CHANGELOG](./CHANGELOG.md) for additional upgrade links.
|
|
1274
1277
|
|
|
1278
|
+
#### Automating Updates with Dependabot
|
|
1279
|
+
|
|
1280
|
+
Shakapacker is shipped as both a Ruby gem and an npm package, so they must be
|
|
1281
|
+
upgraded together. See [Dependabot configuration for Shakapacker](./docs/dependabot.md)
|
|
1282
|
+
for a `.github/dependabot.yml` example that updates both in a single PR.
|
|
1283
|
+
|
|
1275
1284
|
#### Common Upgrade Scenarios
|
|
1276
1285
|
|
|
1277
1286
|
For step-by-step guides on common migrations, see the [Common Upgrades Guide](./docs/common-upgrades.md):
|
|
1278
1287
|
|
|
1279
1288
|
- [Migrating Package Managers](./docs/common-upgrades.md#migrating-package-managers) (Yarn ↔ npm, pnpm)
|
|
1280
|
-
- [Migrating from Babel to SWC](./docs/common-upgrades.md#migrating-from-babel-to-swc) (
|
|
1281
|
-
- [Migrating from Webpack to Rspack](./docs/common-upgrades.md#migrating-from-webpack-to-rspack) (
|
|
1289
|
+
- [Migrating from Babel to SWC](./docs/common-upgrades.md#migrating-from-babel-to-swc) (upstream: ~20x faster transpilation)
|
|
1290
|
+
- [Migrating from Webpack to Rspack](./docs/common-upgrades.md#migrating-from-webpack-to-rspack) (upstream: ~8–17x faster bundler)
|
|
1282
1291
|
|
|
1283
1292
|
### Paths
|
|
1284
1293
|
|
data/lib/install/package.json
CHANGED
data/lib/shakapacker/compiler.rb
CHANGED
|
@@ -9,6 +9,14 @@ class Shakapacker::Compiler
|
|
|
9
9
|
# Shakapacker::Compiler.env['FRONTEND_API_KEY'] = 'your_secret_key'
|
|
10
10
|
cattr_accessor(:env) { {} }
|
|
11
11
|
|
|
12
|
+
# Class-level state keeps the compile-time doctor hint once-per-process.
|
|
13
|
+
@doctor_hint_shown = false
|
|
14
|
+
DOCTOR_HINT_MUTEX = Mutex.new
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
attr_accessor :doctor_hint_shown
|
|
18
|
+
end
|
|
19
|
+
|
|
12
20
|
delegate :config, :logger, :strategy, to: :instance
|
|
13
21
|
delegate :fresh?, :stale?, :after_compile_hook, to: :strategy
|
|
14
22
|
|
|
@@ -184,6 +192,7 @@ class Shakapacker::Compiler
|
|
|
184
192
|
else
|
|
185
193
|
non_empty_streams = [stdout, stderr].delete_if(&:empty?)
|
|
186
194
|
logger.error "\nCOMPILATION FAILED:\nEXIT STATUS: #{status}\nOUTPUTS:\n#{non_empty_streams.join("\n\n")}"
|
|
195
|
+
show_doctor_hint_once
|
|
187
196
|
end
|
|
188
197
|
|
|
189
198
|
status.success?
|
|
@@ -201,4 +210,24 @@ class Shakapacker::Compiler
|
|
|
201
210
|
def bin_shakapacker_path
|
|
202
211
|
config.root_path.join("bin/shakapacker")
|
|
203
212
|
end
|
|
213
|
+
|
|
214
|
+
# Fires only after a failed compile, so users in a healthy loop never see the tip.
|
|
215
|
+
def show_doctor_hint_once
|
|
216
|
+
return if self.class.doctor_hint_shown
|
|
217
|
+
|
|
218
|
+
DOCTOR_HINT_MUTEX.synchronize do
|
|
219
|
+
return if self.class.doctor_hint_shown
|
|
220
|
+
|
|
221
|
+
begin
|
|
222
|
+
logger.info "Tip: run 'bundle exec rake shakapacker:doctor' to diagnose configuration issues."
|
|
223
|
+
rescue StandardError => _e
|
|
224
|
+
# Non-critical tip; never abort a build because the logger failed.
|
|
225
|
+
# Named (but unused) variable makes the deliberate swallow explicit.
|
|
226
|
+
return
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Assignment is outside the rescue so a flag-setter failure propagates rather than being silenced.
|
|
230
|
+
self.class.doctor_hint_shown = true
|
|
231
|
+
end
|
|
232
|
+
end
|
|
204
233
|
end
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -60,6 +60,16 @@ module Shakapacker
|
|
|
60
60
|
add_warning(message, CATEGORY_INFO)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Marks the warning as a Fix sub-item; the renderer owns the "Fix: " prefix and indentation.
|
|
64
|
+
# The stored category mirrors the parent warning so a fix attached to an action-required
|
|
65
|
+
# item is itself action-required (it's only rendered alongside its parent, but the data
|
|
66
|
+
# stays consistent for any downstream consumer).
|
|
67
|
+
def add_fix_hint(message)
|
|
68
|
+
parent = @warnings.reverse_each.find { |w| !w[:fix] }
|
|
69
|
+
category = parent ? parent[:category] : CATEGORY_RECOMMENDED
|
|
70
|
+
@warnings << { category: category, message: message, fix: true }
|
|
71
|
+
end
|
|
72
|
+
|
|
63
73
|
def print_help
|
|
64
74
|
puts <<~HELP
|
|
65
75
|
Shakapacker Doctor - Diagnostic tool for Shakapacker configuration
|
|
@@ -110,6 +120,7 @@ module Shakapacker
|
|
|
110
120
|
check_css_dependencies
|
|
111
121
|
check_css_modules_configuration
|
|
112
122
|
check_bundler_dependencies if config_exists?
|
|
123
|
+
check_rspack_cache_configuration if config_exists?
|
|
113
124
|
check_file_type_dependencies if config_exists?
|
|
114
125
|
check_sri_dependencies if config_exists?
|
|
115
126
|
check_peer_dependencies
|
|
@@ -200,7 +211,7 @@ module Shakapacker
|
|
|
200
211
|
# Match "bundler:" at start of line or preceded by non-underscore character
|
|
201
212
|
if config_file.match?(/^\s*bundler:/m) || config_file.match?(/[^_]bundler:/)
|
|
202
213
|
add_action_required("Deprecated config: 'bundler' should be renamed to 'assets_bundler' in #{config_relative_path}.")
|
|
203
|
-
|
|
214
|
+
add_fix_hint("Open #{config_relative_path} and change 'bundler:' to 'assets_bundler:'.")
|
|
204
215
|
end
|
|
205
216
|
rescue => e
|
|
206
217
|
# Ignore read errors as config file check already handles missing file
|
|
@@ -407,7 +418,7 @@ module Shakapacker
|
|
|
407
418
|
|
|
408
419
|
unless missing_binstubs.empty?
|
|
409
420
|
add_action_required("Missing binstubs: #{missing_binstubs.join(', ')}.")
|
|
410
|
-
|
|
421
|
+
add_fix_hint("Run 'bundle exec rake shakapacker:binstubs' to create them.")
|
|
411
422
|
end
|
|
412
423
|
end
|
|
413
424
|
|
|
@@ -480,7 +491,7 @@ module Shakapacker
|
|
|
480
491
|
else "npm uninstall swc-loader"
|
|
481
492
|
end
|
|
482
493
|
add_warning("swc-loader is not needed with Rspack (SWC is built-in). Rspack includes SWC transpilation natively, so this package is redundant.")
|
|
483
|
-
|
|
494
|
+
add_fix_hint("Remove it with: #{remove_cmd}.")
|
|
484
495
|
end
|
|
485
496
|
end
|
|
486
497
|
end
|
|
@@ -520,7 +531,7 @@ module Shakapacker
|
|
|
520
531
|
babel_files << "package.json" if babel_in_package_json
|
|
521
532
|
babel_files_str = babel_files.join(", ")
|
|
522
533
|
add_warning("Babel configuration files found (#{babel_files_str}) but javascript_transpiler is '#{transpiler}'. These Babel configs are ignored by Shakapacker (though they may still be used by ESLint or other tools).")
|
|
523
|
-
|
|
534
|
+
add_fix_hint("Remove Babel config files if not needed, or set javascript_transpiler: 'babel' in shakapacker.yml to use Babel for transpilation.")
|
|
524
535
|
end
|
|
525
536
|
|
|
526
537
|
# Check for redundant dependencies
|
|
@@ -681,6 +692,307 @@ module Shakapacker
|
|
|
681
692
|
end
|
|
682
693
|
end
|
|
683
694
|
|
|
695
|
+
def check_rspack_cache_configuration
|
|
696
|
+
return unless config.rspack?
|
|
697
|
+
|
|
698
|
+
rspack_major = rspack_major_version
|
|
699
|
+
|
|
700
|
+
if rspack_major == 1
|
|
701
|
+
add_warning("Rspack v1 detected: persistent caching is experimental in v1 and requires manual opt-in. " \
|
|
702
|
+
"Upgrading to Rspack v2 enables stable persistent caching out of the box for significantly faster rebuilds.")
|
|
703
|
+
add_fix_hint("Bump @rspack/core and @rspack/cli to ^2.0.0-0 in package.json. See https://rspack.rs/config/cache and docs/rspack.md for details.")
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
path = active_assets_bundler_config_path
|
|
707
|
+
return unless path
|
|
708
|
+
|
|
709
|
+
content = read_active_assets_bundler_config(path)
|
|
710
|
+
return unless content
|
|
711
|
+
|
|
712
|
+
return unless rspack_cache_disabled?(content)
|
|
713
|
+
|
|
714
|
+
relative = config_path_for_warning(path)
|
|
715
|
+
add_warning("Rspack cache appears to be disabled in #{relative} (found 'cache: false'). Disabling cache " \
|
|
716
|
+
"causes significantly slower builds, especially on rebuilds. Rspack v2 promotes filesystem " \
|
|
717
|
+
"caching from experimental to stable.")
|
|
718
|
+
add_fix_hint("Remove the 'cache: false' setting, or use 'cache: { type: \"filesystem\" }' for persistent caching. " \
|
|
719
|
+
"See https://rspack.rs/config/cache for options.")
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
# Returns the single active config path the runner would load, or nil. Mirrors the
|
|
723
|
+
# resolution order in Shakapacker::Runner#find_rspack_config_with_fallback so the
|
|
724
|
+
# doctor inspects the same file the build will actually use (and so unused sibling
|
|
725
|
+
# configs in the same directory don't trigger spurious warnings).
|
|
726
|
+
# NOTE: keep this candidate list in sync with Runner#find_rspack_config_with_fallback.
|
|
727
|
+
def active_assets_bundler_config_path
|
|
728
|
+
config_dir = config.assets_bundler_config_path.to_s
|
|
729
|
+
|
|
730
|
+
candidates = %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "rspack.config.#{ext}")) }
|
|
731
|
+
candidates += %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "webpack.config.#{ext}")) }
|
|
732
|
+
if default_rspack_config_dir?(config_dir)
|
|
733
|
+
candidates += %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, "config/webpack", "webpack.config.#{ext}")) }
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
candidates.find(&:exist?)
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
def read_active_assets_bundler_config(path)
|
|
740
|
+
File.read(path)
|
|
741
|
+
rescue SystemCallError => e
|
|
742
|
+
add_info_warning("Unable to validate rspack cache configuration: #{e.message}")
|
|
743
|
+
nil
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
def default_rspack_config_dir?(config_dir)
|
|
747
|
+
# Intentionally exact-string match: mirrors the runner's own comparison,
|
|
748
|
+
# so a trailing slash or Pathname argument won't spuriously add the config/webpack fallback.
|
|
749
|
+
config_dir == "config/rspack"
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
def config_path_for_warning(path)
|
|
753
|
+
expanded_root = root_path.expand_path
|
|
754
|
+
expanded_path = path.expand_path
|
|
755
|
+
|
|
756
|
+
return path.to_s unless expanded_path.to_s == expanded_root.to_s ||
|
|
757
|
+
expanded_path.to_s.start_with?("#{expanded_root}#{File::SEPARATOR}")
|
|
758
|
+
|
|
759
|
+
path.relative_path_from(root_path)
|
|
760
|
+
rescue ArgumentError
|
|
761
|
+
path.to_s
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def rspack_cache_disabled?(content)
|
|
765
|
+
stripped = stripped_rspack_config_content(content)
|
|
766
|
+
|
|
767
|
+
direct_export_cache_disabled?(stripped) || exported_variable_cache_disabled?(stripped)
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
def stripped_rspack_config_content(content)
|
|
771
|
+
# Normalize quoted property keys before stripping string literals; otherwise
|
|
772
|
+
# `'cache'` and `"cache"` collapse to `""` and the match below misses them.
|
|
773
|
+
# Lookahead is restricted to horizontal whitespace so a multiline ternary
|
|
774
|
+
# like `condition ? "cache"\n : false` doesn't fold across the newline
|
|
775
|
+
# and produce a spurious cache: false match.
|
|
776
|
+
stripped = content.gsub(/(['"])(\w+)\1(?=[ \t]*:)/, '\2')
|
|
777
|
+
|
|
778
|
+
stripped = strip_rspack_config_comments_and_literals(stripped)
|
|
779
|
+
|
|
780
|
+
# Regex literal stripping runs after comment removal. The line-comment
|
|
781
|
+
# pass above ignores escaped slashes so /https?:\/\/host/ stays intact
|
|
782
|
+
# until this pass removes the whole regex literal. The heuristic can
|
|
783
|
+
# false-match bare division like `a / b / c`, but rspack config files
|
|
784
|
+
# rarely contain arithmetic near `cache:`, so the risk is low.
|
|
785
|
+
stripped.gsub(%r{/(?:\\.|\[[^\]\n]*\]|[^/\n\\\[])+?/[gimsuy]*}, "")
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
def strip_rspack_config_comments_and_literals(content)
|
|
789
|
+
stripped = +""
|
|
790
|
+
index = 0
|
|
791
|
+
|
|
792
|
+
while index < content.length
|
|
793
|
+
char = content[index]
|
|
794
|
+
pair = content[index, 2]
|
|
795
|
+
|
|
796
|
+
if pair == "/*"
|
|
797
|
+
comment_end = content.index("*/", index + 2)
|
|
798
|
+
if comment_end
|
|
799
|
+
comment = content[index..comment_end + 1]
|
|
800
|
+
stripped << comment.gsub(/[^\n]/, " ")
|
|
801
|
+
index = comment_end + 2
|
|
802
|
+
else
|
|
803
|
+
stripped << content[index..].gsub(/[^\n]/, " ")
|
|
804
|
+
break
|
|
805
|
+
end
|
|
806
|
+
elsif pair == "//"
|
|
807
|
+
line_end = content.index("\n", index + 2) || content.length
|
|
808
|
+
stripped << content[index...line_end].gsub(/[^\n]/, " ")
|
|
809
|
+
index = line_end
|
|
810
|
+
elsif char == "'" || char == '"'
|
|
811
|
+
literal_end = index + 1
|
|
812
|
+
escaped = false
|
|
813
|
+
|
|
814
|
+
while literal_end < content.length
|
|
815
|
+
current = content[literal_end]
|
|
816
|
+
break if current == "\n"
|
|
817
|
+
|
|
818
|
+
if escaped
|
|
819
|
+
escaped = false
|
|
820
|
+
elsif current == "\\"
|
|
821
|
+
escaped = true
|
|
822
|
+
elsif current == char
|
|
823
|
+
literal_end += 1
|
|
824
|
+
break
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
literal_end += 1
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
literal = content[index...literal_end]
|
|
831
|
+
stripped << '""'
|
|
832
|
+
stripped << literal.gsub(/[^\n]/, "")
|
|
833
|
+
index = literal_end
|
|
834
|
+
elsif char == "`"
|
|
835
|
+
literal_end = index + 1
|
|
836
|
+
escaped = false
|
|
837
|
+
closed = false
|
|
838
|
+
|
|
839
|
+
while literal_end < content.length
|
|
840
|
+
current = content[literal_end]
|
|
841
|
+
|
|
842
|
+
if escaped
|
|
843
|
+
escaped = false
|
|
844
|
+
elsif current == "\\"
|
|
845
|
+
escaped = true
|
|
846
|
+
elsif current == "`"
|
|
847
|
+
literal_end += 1
|
|
848
|
+
closed = true
|
|
849
|
+
break
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
literal_end += 1
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
if closed
|
|
856
|
+
literal = content[index...literal_end]
|
|
857
|
+
stripped << '""'
|
|
858
|
+
stripped << literal.gsub(/[^\n]/, "")
|
|
859
|
+
index = literal_end
|
|
860
|
+
else
|
|
861
|
+
stripped << char
|
|
862
|
+
index += 1
|
|
863
|
+
end
|
|
864
|
+
else
|
|
865
|
+
stripped << char
|
|
866
|
+
index += 1
|
|
867
|
+
end
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
stripped
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
def direct_export_cache_disabled?(stripped)
|
|
874
|
+
# Match `cache: false` only near an exported config object at brace depth
|
|
875
|
+
# 1. This avoids warning on local base config objects while still
|
|
876
|
+
# catching the common direct export and generateRspackConfig patterns.
|
|
877
|
+
#
|
|
878
|
+
# Known false-positive gaps (rare; the "appears to be disabled" wording
|
|
879
|
+
# is the user-visible mitigation):
|
|
880
|
+
# * Named intermediate export — `export const helper = { cache: false }`
|
|
881
|
+
# at depth 1 is flagged even when `helper` is not the final config and
|
|
882
|
+
# a separate `export default { … }` provides the real configuration.
|
|
883
|
+
# * ASI + prior `module.exports` — in semicolon-free code, an earlier
|
|
884
|
+
# `module.exports = merge(…)` followed by a local helper literal can
|
|
885
|
+
# leak into `statement_prefix` because `pre.rindex(";")` returns nil
|
|
886
|
+
# and the prefix spans back to the start of the file.
|
|
887
|
+
stripped.to_enum(:scan, /\bcache\s*:\s*false\b/).any? do
|
|
888
|
+
pre = Regexp.last_match.pre_match
|
|
889
|
+
next false unless (pre.count("{") - pre.count("}")) == 1
|
|
890
|
+
|
|
891
|
+
statement_prefix = pre[(pre.rindex(";") || -1) + 1..]
|
|
892
|
+
# generateRspackConfig is Shakapacker's own helper; user-defined wrappers
|
|
893
|
+
# like makeRspackConfig/createConfig are a known false-negative gap.
|
|
894
|
+
statement_prefix.match?(/\bmodule\.exports\b|\bexport\s+default\b|\bexport\s+(?:const|let|var)\b|\bgenerateRspackConfig\b/)
|
|
895
|
+
end
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
# Catches the `const cfg = { cache: false }; module.exports = cfg` pattern.
|
|
899
|
+
# Composition via merge (`module.exports = merge(cfg, …)`) is a known
|
|
900
|
+
# false-negative since the variable is never referenced by name in the
|
|
901
|
+
# export statement. The `[^=;]+` type-annotation clause also stops at the
|
|
902
|
+
# first `=`, so TypeScript generics with default type parameters such as
|
|
903
|
+
# `Configuration<Opts = DefaultOpts>` are another known false-negative gap.
|
|
904
|
+
def exported_variable_cache_disabled?(stripped)
|
|
905
|
+
variable_declaration = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)(?:\s*:\s*[^=;]+)?\s*=\s*\{/
|
|
906
|
+
|
|
907
|
+
stripped.to_enum(:scan, variable_declaration).any? do
|
|
908
|
+
name = Regexp.last_match[1]
|
|
909
|
+
open_index = Regexp.last_match.end(0) - 1
|
|
910
|
+
close_index = matching_closing_brace(stripped, open_index)
|
|
911
|
+
next false unless close_index
|
|
912
|
+
|
|
913
|
+
object_source = stripped[open_index..close_index]
|
|
914
|
+
top_level_cache_false?(object_source) && exported_config_variable?(stripped, name)
|
|
915
|
+
end
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
def top_level_cache_false?(object_source)
|
|
919
|
+
object_source.to_enum(:scan, /\bcache\s*:\s*false\b/).any? do
|
|
920
|
+
pre = Regexp.last_match.pre_match
|
|
921
|
+
(pre.count("{") - pre.count("}")) == 1
|
|
922
|
+
end
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
def exported_config_variable?(stripped, name)
|
|
926
|
+
escaped_name = Regexp.escape(name)
|
|
927
|
+
stripped.match?(/\bmodule\.exports\s*=\s*#{escaped_name}\b/) ||
|
|
928
|
+
stripped.match?(/\bexport\s+default\s+#{escaped_name}\b/) ||
|
|
929
|
+
stripped.match?(/\bexport\s*\{[^}]*\b#{escaped_name}\s+as\s+default\b/)
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
def matching_closing_brace(content, open_index)
|
|
933
|
+
depth = 0
|
|
934
|
+
|
|
935
|
+
content[open_index..].each_char.with_index do |char, offset|
|
|
936
|
+
depth += 1 if char == "{"
|
|
937
|
+
depth -= 1 if char == "}"
|
|
938
|
+
|
|
939
|
+
return open_index + offset if depth.zero?
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
nil
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
def rspack_major_version
|
|
946
|
+
# Prefer the resolved version from node_modules, since package.json specifiers
|
|
947
|
+
# (ranges, git refs, file paths) often don't parse to a clean major number.
|
|
948
|
+
resolved = installed_rspack_major_version
|
|
949
|
+
return resolved unless resolved.nil?
|
|
950
|
+
|
|
951
|
+
%w[@rspack/core @rspack/cli].each do |package_name|
|
|
952
|
+
major = rspack_major_from_specifier(package_json_dependency_version(package_name))
|
|
953
|
+
return major unless major.nil?
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
nil
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
def rspack_major_from_specifier(version)
|
|
960
|
+
return nil unless version
|
|
961
|
+
|
|
962
|
+
# Only trust specifiers starting with a digit or ^/~ prefix followed by
|
|
963
|
+
# a digit. Skip git+, file:, npm: aliases, "latest", "*", or ranges like
|
|
964
|
+
# ">=1.5 <2". Accept shorthand forms (e.g. `^1`, `~1`, `1`, `1.x`) so
|
|
965
|
+
# we still emit the v1 advisory when node_modules isn't populated yet.
|
|
966
|
+
cleaned = version.strip
|
|
967
|
+
return nil unless cleaned.match?(/\A[\^~]?\d/)
|
|
968
|
+
return nil if cleaned.match?(/(\s|\|\||[<>=:]|\A(?:git|file|link|workspace|npm):)/)
|
|
969
|
+
return nil unless cleaned.match?(/\A[\^~]?\d+(?:\.(?:\d+|x|\*)){0,2}(?:-[0-9A-Za-z.-]+)?\z/i)
|
|
970
|
+
|
|
971
|
+
match = cleaned.sub(/\A[\^~]/, "").match(/\A(\d+)/)
|
|
972
|
+
match && match[1].to_i
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
def installed_rspack_major_version
|
|
976
|
+
rspack_pkg = root_path.join("node_modules/@rspack/core/package.json")
|
|
977
|
+
return nil unless rspack_pkg.exist?
|
|
978
|
+
|
|
979
|
+
version = JSON.parse(File.read(rspack_pkg))["version"]
|
|
980
|
+
match = version.to_s.match(/\A(\d+)\./)
|
|
981
|
+
match && match[1].to_i
|
|
982
|
+
rescue JSON::ParserError, SystemCallError
|
|
983
|
+
nil
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
def package_json_dependency_version(name)
|
|
987
|
+
return nil unless package_json_exists?
|
|
988
|
+
|
|
989
|
+
pkg = read_package_json
|
|
990
|
+
# Production dependencies take precedence on key conflict so the version
|
|
991
|
+
# actually shipped in production wins over a devDependencies override.
|
|
992
|
+
deps = (pkg["devDependencies"] || {}).merge(pkg["dependencies"] || {})
|
|
993
|
+
deps[name]
|
|
994
|
+
end
|
|
995
|
+
|
|
684
996
|
def check_file_type_dependencies
|
|
685
997
|
source_path = config.source_path
|
|
686
998
|
return unless source_path.exist?
|
|
@@ -1064,15 +1376,14 @@ module Shakapacker
|
|
|
1064
1376
|
end
|
|
1065
1377
|
|
|
1066
1378
|
def print_warnings
|
|
1067
|
-
|
|
1068
|
-
main_item_count = doctor.warnings.count { |w| !w[:message].start_with?(" ") }
|
|
1379
|
+
main_item_count = doctor.warnings.count { |w| !subitem?(w) }
|
|
1069
1380
|
puts "⚠️ Warnings (#{main_item_count}):"
|
|
1070
1381
|
puts ""
|
|
1071
1382
|
|
|
1072
1383
|
item_number = 0
|
|
1073
1384
|
doctor.warnings.each do |warning|
|
|
1074
|
-
if subitem?(warning
|
|
1075
|
-
print_subitem(warning
|
|
1385
|
+
if subitem?(warning)
|
|
1386
|
+
print_subitem(warning)
|
|
1076
1387
|
else
|
|
1077
1388
|
item_number += 1
|
|
1078
1389
|
print_main_item(item_number, warning)
|
|
@@ -1081,15 +1392,16 @@ module Shakapacker
|
|
|
1081
1392
|
puts ""
|
|
1082
1393
|
end
|
|
1083
1394
|
|
|
1084
|
-
def subitem?(
|
|
1085
|
-
message.start_with?(" ")
|
|
1395
|
+
def subitem?(warning)
|
|
1396
|
+
warning[:fix] || warning[:message].start_with?(" ")
|
|
1086
1397
|
end
|
|
1087
1398
|
|
|
1088
|
-
def print_subitem(
|
|
1399
|
+
def print_subitem(warning)
|
|
1089
1400
|
# Fix instructions align at column 16 (length of "N. [RECOMMENDED] ")
|
|
1090
|
-
# This
|
|
1401
|
+
# This keeps every Fix line aligned regardless of category.
|
|
1091
1402
|
subitem_prefix = " " * 15
|
|
1092
|
-
|
|
1403
|
+
text = warning[:fix] ? "Fix: #{warning[:message]}" : warning[:message]
|
|
1404
|
+
wrapped = wrap_text(text, 100, subitem_prefix)
|
|
1093
1405
|
puts wrapped
|
|
1094
1406
|
end
|
|
1095
1407
|
|
data/lib/shakapacker/version.rb
CHANGED