shakapacker 8.4.0 → 9.0.0.beta.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/STATUS.md +1 -0
  3. data/.github/workflows/dummy.yml +1 -1
  4. data/.github/workflows/generator.yml +4 -14
  5. data/.github/workflows/node.yml +1 -1
  6. data/CHANGELOG.md +4 -2
  7. data/Gemfile.lock +3 -3
  8. data/README.md +2 -2
  9. data/docs/css-modules-export-mode.md +288 -0
  10. data/docs/peer-dependencies.md +40 -0
  11. data/docs/rspack.md +190 -0
  12. data/docs/troubleshooting.md +5 -0
  13. data/lib/install/bin/shakapacker +14 -2
  14. data/lib/install/bin/shakapacker-rspack +13 -0
  15. data/lib/install/config/rspack/rspack.config.js +6 -0
  16. data/lib/install/config/shakapacker.yml +3 -0
  17. data/lib/install/package.json +30 -0
  18. data/lib/install/template.rb +12 -2
  19. data/lib/shakapacker/configuration.rb +12 -0
  20. data/lib/shakapacker/dev_server_runner.rb +17 -7
  21. data/lib/shakapacker/manifest.rb +3 -2
  22. data/lib/shakapacker/rspack_runner.rb +57 -0
  23. data/lib/shakapacker/runner.rb +48 -2
  24. data/lib/shakapacker/version.rb +1 -1
  25. data/package/environments/base.js +10 -65
  26. data/package/environments/development.js +18 -3
  27. data/package/environments/production.js +24 -51
  28. data/package/environments/test.js +15 -1
  29. data/package/index.d.ts +14 -0
  30. data/package/index.js +4 -2
  31. data/package/optimization/rspack.js +25 -0
  32. data/package/optimization/webpack.js +49 -0
  33. data/package/plugins/rspack.js +104 -0
  34. data/package/plugins/webpack.js +62 -0
  35. data/package/rules/css.js +1 -1
  36. data/package/rules/file.js +11 -5
  37. data/package/rules/less.js +1 -1
  38. data/package/rules/raw.js +11 -1
  39. data/package/rules/rspack.js +96 -0
  40. data/package/rules/sass.js +6 -2
  41. data/package/rules/stylus.js +1 -1
  42. data/package/utils/getStyleRule.js +16 -3
  43. data/package/utils/requireOrError.js +15 -0
  44. data/package.json +19 -31
  45. data/test/package/environments/base.test.js +1 -1
  46. data/test/package/rules/{index.test.js → webpack.test.js} +1 -1
  47. data/yarn.lock +2136 -726
  48. metadata +21 -11
  49. /data/package/rules/{index.js → webpack.js} +0 -0
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV["RAILS_ENV"] ||= "development"
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
5
+
6
+ require "bundler/setup"
7
+ require "shakapacker"
8
+ require "shakapacker/rspack_runner"
9
+
10
+ APP_ROOT = File.expand_path("..", __dir__)
11
+ Dir.chdir(APP_ROOT) do
12
+ Shakapacker::RspackRunner.run(ARGV)
13
+ end
@@ -0,0 +1,6 @@
1
+ // See the shakacode/shakapacker README and docs directory for advice on customizing your rspackConfig.
2
+ const { generateRspackConfig } = require('shakapacker/rspack')
3
+
4
+ const rspackConfig = generateRspackConfig()
5
+
6
+ module.exports = rspackConfig
@@ -39,6 +39,9 @@ default: &default
39
39
  # Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
40
40
  webpack_loader: 'babel'
41
41
 
42
+ # Select bundler to use, available options are 'webpack' (default) or 'rspack'
43
+ bundler: 'webpack'
44
+
42
45
  # Raises an error if there is a mismatch in the shakapacker gem and npm package being used
43
46
  ensure_consistent_versioning: true
44
47
 
@@ -0,0 +1,30 @@
1
+ {
2
+ "rspack": {
3
+ "@rspack/cli": "^1.0.0",
4
+ "@rspack/core": "^1.0.0",
5
+ "rspack-manifest-plugin": "^5.0.0"
6
+ },
7
+ "webpack": {
8
+ "mini-css-extract-plugin": "^2.0.0",
9
+ "terser-webpack-plugin": "^5.3.1",
10
+ "webpack": "^5.76.0",
11
+ "webpack-assets-manifest": "^5.0.6 || ^6.0.0",
12
+ "webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0",
13
+ "webpack-dev-server": "^4.15.2 || ^5.2.2",
14
+ "webpack-merge": "^5.8.0 || ^6.0.0",
15
+ "webpack-subresource-integrity": "^5.1.0"
16
+ },
17
+ "common": {
18
+ "compression-webpack-plugin": "^9.0.0 || ^10.0.0|| ^11.0.0",
19
+ "css-loader": "^6.0.0 || ^7.0.0",
20
+ "sass-loader": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
21
+ "style-loader": "^3.0.0 || ^4.0.0"
22
+ },
23
+ "babel": {
24
+ "@babel/core": "^7.17.9",
25
+ "@babel/plugin-transform-runtime": "^7.17.0",
26
+ "@babel/preset-env": "^7.16.11",
27
+ "@babel/runtime": "^7.17.9",
28
+ "babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0"
29
+ }
30
+ }
@@ -8,7 +8,6 @@ require "package_json"
8
8
  force_option = ENV["FORCE"] ? { force: true } : {}
9
9
 
10
10
  copy_file "#{__dir__}/config/shakapacker.yml", "config/shakapacker.yml", force_option
11
- remove_file "#{__dir__}/package.json" if force_option[:force]
12
11
 
13
12
  say "Copying webpack core config"
14
13
  directory "#{__dir__}/config/webpack", "config/webpack", force_option
@@ -112,7 +111,15 @@ rescue PackageJson::Error
112
111
  end
113
112
 
114
113
  def fetch_peer_dependencies
115
- PackageJson.read("#{__dir__}/../../").fetch("peerDependencies")
114
+ PackageJson.read("#{__dir__}").fetch(ENV["SHAKAPACKER_BUNDLER"] || "webpack")
115
+ end
116
+
117
+ def fetch_common_dependencies
118
+ ENV["SKIP_COMMON_LOADERS"] ? {} : PackageJson.read("#{__dir__}").fetch("common")
119
+ end
120
+
121
+ def fetch_babel_dependencies
122
+ ENV["USE_BABEL_PACKAGES"] ? PackageJson.read("#{__dir__}").fetch("babel") : {}
116
123
  end
117
124
 
118
125
  Dir.chdir(Rails.root) do
@@ -130,6 +137,9 @@ Dir.chdir(Rails.root) do
130
137
  end
131
138
 
132
139
  peers = fetch_peer_dependencies
140
+ peers = peers.merge(fetch_common_dependencies)
141
+ peers = peers.merge(fetch_babel_dependencies)
142
+
133
143
  dev_dependency_packages = ["webpack-dev-server"]
134
144
 
135
145
  dependencies_to_add = []
@@ -88,6 +88,18 @@ class Shakapacker::Configuration
88
88
  fetch(:compiler_strategy)
89
89
  end
90
90
 
91
+ def bundler
92
+ fetch(:bundler) || "webpack"
93
+ end
94
+
95
+ def rspack?
96
+ bundler == "rspack"
97
+ end
98
+
99
+ def webpack?
100
+ bundler == "webpack"
101
+ end
102
+
91
103
  def fetch(key)
92
104
  data.fetch(key, defaults[key])
93
105
  end
@@ -75,12 +75,20 @@ module Shakapacker
75
75
  env["NODE_OPTIONS"] = "#{env["NODE_OPTIONS"]} --inspect-brk --trace-warnings"
76
76
  end
77
77
 
78
- cmd += ["--config", @webpack_config]
79
- cmd += ["--progress", "--color"] if @pretty
80
-
81
- # Default behavior of webpack-dev-server is @hot = true
82
- cmd += ["--hot", "only"] if @hot == "only"
83
- cmd += ["--no-hot"] if !@hot
78
+ # Add bundler-specific flags and config
79
+ bundler = get_bundler_type
80
+ if bundler == "webpack"
81
+ cmd += ["--config", @webpack_config]
82
+ cmd += ["--progress", "--color"] if @pretty
83
+ # Default behavior of webpack-dev-server is @hot = true
84
+ cmd += ["--hot", "only"] if @hot == "only"
85
+ cmd += ["--no-hot"] if !@hot
86
+ elsif bundler == "rspack"
87
+ # Only add config for rspack if it's not a rspack-specific command
88
+ cmd += ["--config", @webpack_config]
89
+ # Rspack supports --hot but not --no-hot or --progress/--color
90
+ cmd += ["--hot"] if @hot && @hot != false
91
+ end
84
92
 
85
93
  cmd += @argv
86
94
 
@@ -90,7 +98,9 @@ module Shakapacker
90
98
  end
91
99
 
92
100
  def build_cmd
93
- package_json.manager.native_exec_command("webpack", ["serve"])
101
+ bundler = get_bundler_type
102
+ command = bundler == "rspack" ? "rspack" : "webpack"
103
+ package_json.manager.native_exec_command(command, ["serve"])
94
104
  end
95
105
  end
96
106
  end
@@ -114,9 +114,10 @@ Shakapacker can't find #{bundle_name} in #{config.manifest_path}. Possible cause
114
114
  2. Your app has code with a non-standard extension (like a `.jsx` file) but the extension is not in the `extensions` config in `config/shakapacker.yml`
115
115
  3. You have set compile: false (see `config/shakapacker.yml`) for this environment
116
116
  (unless you are using the `bin/shakapacker -w` or the `bin/shakapacker-dev-server`, in which case maybe you aren't running the dev server in the background?)
117
- 4. webpack has not yet FINISHED running to reflect updates.
117
+ 4. Your bundler (webpack/rspack) has not yet FINISHED running to reflect updates.
118
118
  5. You have misconfigured Shakapacker's `config/shakapacker.yml` file.
119
- 6. Your webpack configuration is not creating a manifest.
119
+ 6. Your bundler configuration is not creating a manifest with the expected structure.
120
+ 7. There's a mismatch between your bundler choice (webpack vs rspack) and the manifest format.
120
121
 
121
122
  Your manifest contains:
122
123
  #{JSON.pretty_generate(@data)}
@@ -0,0 +1,57 @@
1
+ require "shellwords"
2
+
3
+ require_relative "runner"
4
+
5
+ module Shakapacker
6
+ class RspackRunner < Shakapacker::Runner
7
+ RSPACK_COMMANDS = [
8
+ "help",
9
+ "h",
10
+ "--help",
11
+ "-h",
12
+ "version",
13
+ "v",
14
+ "--version",
15
+ "-v",
16
+ "info",
17
+ "i"
18
+ ].freeze
19
+
20
+ def run
21
+ env = Shakapacker::Compiler.env
22
+ env["SHAKAPACKER_CONFIG"] = @shakapacker_config
23
+ env["NODE_OPTIONS"] = ENV["NODE_OPTIONS"] || ""
24
+
25
+ cmd = build_cmd
26
+
27
+ if @argv.delete("--debug-shakapacker")
28
+ env["NODE_OPTIONS"] = "#{env["NODE_OPTIONS"]} --inspect-brk"
29
+ end
30
+
31
+ if @argv.delete "--trace-deprecation"
32
+ env["NODE_OPTIONS"] = "#{env["NODE_OPTIONS"]} --trace-deprecation"
33
+ end
34
+
35
+ if @argv.delete "--no-deprecation"
36
+ env["NODE_OPTIONS"] = "#{env["NODE_OPTIONS"]} --no-deprecation"
37
+ end
38
+
39
+ # Rspack commands are not compatible with --config option.
40
+ if (@argv & RSPACK_COMMANDS).empty?
41
+ cmd += ["--config", @webpack_config]
42
+ end
43
+
44
+ cmd += @argv
45
+
46
+ Dir.chdir(@app_path) do
47
+ Kernel.exec env, *cmd
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def build_cmd
54
+ package_json.manager.native_exec_command("rspack")
55
+ end
56
+ end
57
+ end
@@ -1,7 +1,9 @@
1
1
  require_relative "utils/misc"
2
2
  require_relative "utils/manager"
3
+ require_relative "configuration"
3
4
 
4
5
  require "package_json"
6
+ require "pathname"
5
7
 
6
8
  module Shakapacker
7
9
  class Runner
@@ -16,7 +18,12 @@ module Shakapacker
16
18
 
17
19
  @app_path = File.expand_path(".", Dir.pwd)
18
20
  @shakapacker_config = ENV["SHAKAPACKER_CONFIG"] || File.join(@app_path, "config/shakapacker.yml")
19
- @webpack_config = find_webpack_config
21
+ @config = Configuration.new(
22
+ root_path: Pathname.new(@app_path),
23
+ config_path: Pathname.new(@shakapacker_config),
24
+ env: ENV["RAILS_ENV"] || ENV["NODE_ENV"] || "development"
25
+ )
26
+ @webpack_config = find_bundler_config
20
27
 
21
28
  Shakapacker::Utils::Manager.error_unless_package_manager_is_obvious!
22
29
  end
@@ -26,6 +33,45 @@ module Shakapacker
26
33
  end
27
34
 
28
35
  private
36
+ def find_bundler_config
37
+ if @config.rspack?
38
+ find_rspack_config_with_fallback
39
+ else
40
+ find_webpack_config
41
+ end
42
+ end
43
+
44
+ def get_bundler_type
45
+ @config.bundler
46
+ end
47
+
48
+ def find_rspack_config_with_fallback
49
+ # First try rspack-specific paths
50
+ rspack_paths = %w[ts js].map do |ext|
51
+ File.join(@app_path, "config/rspack/rspack.config.#{ext}")
52
+ end
53
+
54
+ rspack_path = rspack_paths.find { |f| File.exist?(f) }
55
+ return rspack_path if rspack_path
56
+
57
+ # Fallback to webpack config with deprecation warning
58
+ webpack_paths = %w[ts js].map do |ext|
59
+ File.join(@app_path, "config/webpack/webpack.config.#{ext}")
60
+ end
61
+
62
+ webpack_path = webpack_paths.find { |f| File.exist?(f) }
63
+ if webpack_path
64
+ $stderr.puts "⚠️ DEPRECATION WARNING: Using webpack config file for Rspack bundler."
65
+ $stderr.puts " Please create config/rspack/rspack.config.js and migrate your configuration."
66
+ $stderr.puts " Using: #{webpack_path}"
67
+ return webpack_path
68
+ end
69
+
70
+ # No config found
71
+ $stderr.puts "rspack config #{rspack_paths.last} not found, please run 'bundle exec rails shakapacker:install' to install Shakapacker with default configs or create the missing config file."
72
+ exit(1)
73
+ end
74
+
29
75
  def find_webpack_config
30
76
  possible_paths = %w[ts js].map do |ext|
31
77
  File.join(@app_path, "config/webpack/webpack.config.#{ext}")
@@ -33,7 +79,7 @@ module Shakapacker
33
79
  path = possible_paths.find { |f| File.exist?(f) }
34
80
  unless path
35
81
  $stderr.puts "webpack config #{possible_paths.last} not found, please run 'bundle exec rails shakapacker:install' to install Shakapacker with default configs or add the missing config file for your custom environment."
36
- exit!
82
+ exit(1)
37
83
  end
38
84
  path
39
85
  end
@@ -1,4 +1,4 @@
1
1
  module Shakapacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "8.4.0".freeze
3
+ VERSION = "9.0.0.beta.0".freeze
4
4
  end
@@ -1,16 +1,20 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
- const { existsSync, readdirSync } = require("fs")
5
4
  const { basename, dirname, join, relative, resolve } = require("path")
5
+ const { existsSync, readdirSync } = require("fs")
6
6
  const extname = require("path-complete-extname")
7
- // TODO: Change to `const { WebpackAssetsManifest }` when dropping 'webpack-assets-manifest < 6.0.0' (Node >=20.10.0) support
8
- const WebpackAssetsManifest = require("webpack-assets-manifest")
9
- const webpack = require("webpack")
10
- const rules = require("../rules")
11
7
  const config = require("../config")
12
8
  const { isProduction } = require("../env")
13
- const { moduleExists } = require("../utils/helpers")
9
+
10
+ const pluginsPath = resolve(__dirname, "..", "plugins", `${config.bundler}.js`)
11
+ const { getPlugins } = require(pluginsPath)
12
+ const rulesPath = resolve(__dirname, "..", "rules", `${config.bundler}.js`)
13
+ const rules = require(rulesPath)
14
+
15
+ // Don't use contentHash except for production for performance
16
+ // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
17
+ const hash = isProduction || config.useContentHash ? "-[contenthash]" : ""
14
18
 
15
19
  const getFilesInDirectory = (dir, includeNested) => {
16
20
  if (!existsSync(dir)) {
@@ -73,63 +77,6 @@ const getModulePaths = () => {
73
77
  return result
74
78
  }
75
79
 
76
- // TODO: Remove WebpackAssetsManifestConstructor workaround when dropping 'webpack-assets-manifest < 6.0.0' (Node >=20.10.0) support
77
- const WebpackAssetsManifestConstructor =
78
- "WebpackAssetsManifest" in WebpackAssetsManifest
79
- ? WebpackAssetsManifest.WebpackAssetsManifest
80
- : WebpackAssetsManifest
81
- const getPlugins = () => {
82
- const plugins = [
83
- new webpack.EnvironmentPlugin(process.env),
84
- new WebpackAssetsManifestConstructor({
85
- entrypoints: true,
86
- writeToDisk: true,
87
- output: config.manifestPath,
88
- entrypointsUseAssets: true,
89
- publicPath: config.publicPathWithoutCDN,
90
- integrity: config.integrity.enabled,
91
- integrityHashes: config.integrity.hash_functions
92
- })
93
- ]
94
-
95
- if (moduleExists("css-loader") && moduleExists("mini-css-extract-plugin")) {
96
- const hash = isProduction || config.useContentHash ? "-[contenthash:8]" : ""
97
- const MiniCssExtractPlugin = require("mini-css-extract-plugin")
98
- plugins.push(
99
- new MiniCssExtractPlugin({
100
- filename: `css/[name]${hash}.css`,
101
- chunkFilename: `css/[id]${hash}.css`,
102
- // For projects where css ordering has been mitigated through consistent use of scoping or naming conventions,
103
- // the css order warnings can be disabled by setting the ignoreOrder flag.
104
- // Read: https://stackoverflow.com/questions/51971857/mini-css-extract-plugin-warning-in-chunk-chunkname-mini-css-extract-plugin-con
105
- ignoreOrder: config.css_extract_ignore_order_warnings
106
- })
107
- )
108
- }
109
-
110
- if (
111
- moduleExists("webpack-subresource-integrity") &&
112
- config.integrity.enabled
113
- ) {
114
- const {
115
- SubresourceIntegrityPlugin
116
- } = require("webpack-subresource-integrity")
117
-
118
- plugins.push(
119
- new SubresourceIntegrityPlugin({
120
- hashFuncNames: config.integrity.hash_functions,
121
- enabled: isProduction
122
- })
123
- )
124
- }
125
-
126
- return plugins
127
- }
128
-
129
- // Don't use contentHash except for production for performance
130
- // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
131
- const hash = isProduction || config.useContentHash ? "-[contenthash]" : ""
132
-
133
80
  module.exports = {
134
81
  mode: "production",
135
82
  output: {
@@ -160,12 +107,10 @@ module.exports = {
160
107
 
161
108
  optimization: {
162
109
  splitChunks: { chunks: "all" },
163
-
164
110
  runtimeChunk: "single"
165
111
  },
166
112
 
167
113
  module: {
168
- strictExportPresence: true,
169
114
  rules
170
115
  }
171
116
  }
@@ -1,13 +1,28 @@
1
1
  const { merge } = require("webpack-merge")
2
-
2
+ const config = require("../config")
3
3
  const baseConfig = require("./base")
4
4
  const webpackDevServerConfig = require("../webpackDevServerConfig")
5
5
  const { runningWebpackDevServer } = require("../env")
6
6
 
7
- const devConfig = {
7
+ const webpackDevConfig = {
8
8
  mode: "development",
9
9
  devtool: "cheap-module-source-map",
10
10
  ...(runningWebpackDevServer && { devServer: webpackDevServerConfig() })
11
11
  }
12
12
 
13
- module.exports = merge(baseConfig, devConfig)
13
+ const rspackDevConfig = {
14
+ mode: "development",
15
+ devtool: "cheap-module-source-map",
16
+ // Force writing assets to disk in development for Rails compatibility
17
+ devServer: {
18
+ ...webpackDevServerConfig(),
19
+ devMiddleware: {
20
+ writeToDisk: true
21
+ }
22
+ }
23
+ }
24
+
25
+ const bundlerConfig =
26
+ config.bundler === "rspack" ? rspackDevConfig : webpackDevConfig
27
+
28
+ module.exports = merge(baseConfig, bundlerConfig)
@@ -2,46 +2,44 @@
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
4
  const { merge } = require("webpack-merge")
5
- const CompressionPlugin = require("compression-webpack-plugin")
6
- const TerserPlugin = require("terser-webpack-plugin")
5
+ const { resolve } = require("path")
7
6
  const baseConfig = require("./base")
8
7
  const { moduleExists } = require("../utils/helpers")
9
8
  const config = require("../config")
10
9
 
10
+ const path = resolve(__dirname, "..", "optimization", `${config.bundler}.js`)
11
+ const { getOptimization } = require(path)
12
+
13
+ let CompressionPlugin = null
14
+ if (moduleExists("compression-webpack-plugin")) {
15
+ // eslint-disable-next-line global-require
16
+ CompressionPlugin = require("compression-webpack-plugin")
17
+ }
18
+
11
19
  const getPlugins = () => {
12
20
  const plugins = []
13
21
 
14
- plugins.push(
15
- new CompressionPlugin({
16
- filename: "[path][base].gz[query]",
17
- algorithm: "gzip",
18
- test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
19
- })
20
- )
21
-
22
- if ("brotli" in process.versions) {
22
+ if (CompressionPlugin) {
23
23
  plugins.push(
24
24
  new CompressionPlugin({
25
- filename: "[path][base].br[query]",
26
- algorithm: "brotliCompress",
25
+ filename: "[path][base].gz[query]",
26
+ algorithm: "gzip",
27
27
  test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
28
28
  })
29
29
  )
30
- }
31
30
 
32
- return plugins
33
- }
34
-
35
- const tryCssMinimizer = () => {
36
- if (
37
- moduleExists("css-loader") &&
38
- moduleExists("css-minimizer-webpack-plugin")
39
- ) {
40
- const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
41
- return new CssMinimizerPlugin()
31
+ if ("brotli" in process.versions) {
32
+ plugins.push(
33
+ new CompressionPlugin({
34
+ filename: "[path][base].br[query]",
35
+ algorithm: "brotliCompress",
36
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
37
+ })
38
+ )
39
+ }
42
40
  }
43
41
 
44
- return null
42
+ return plugins
45
43
  }
46
44
 
47
45
  const productionConfig = {
@@ -49,32 +47,7 @@ const productionConfig = {
49
47
  stats: "normal",
50
48
  bail: true,
51
49
  plugins: getPlugins(),
52
- optimization: {
53
- minimizer: [
54
- tryCssMinimizer(),
55
- new TerserPlugin({
56
- parallel: Number.parseInt(process.env.SHAKAPACKER_PARALLEL, 10) || true,
57
- terserOptions: {
58
- parse: {
59
- // Let terser parse ecma 8 code but always output
60
- // ES5 compliant code for older browsers
61
- ecma: 8
62
- },
63
- compress: {
64
- ecma: 5,
65
- warnings: false,
66
- comparisons: false
67
- },
68
- mangle: { safari10: true },
69
- output: {
70
- ecma: 5,
71
- comments: false,
72
- ascii_only: true
73
- }
74
- }
75
- })
76
- ].filter(Boolean)
77
- }
50
+ optimization: getOptimization()
78
51
  }
79
52
 
80
53
  if (config.useContentHash === false) {
@@ -1,3 +1,17 @@
1
+ const { merge } = require("webpack-merge")
2
+ const config = require("../config")
1
3
  const baseConfig = require("./base")
2
4
 
3
- module.exports = baseConfig
5
+ const rspackTestConfig = {
6
+ mode: "development",
7
+ devtool: "cheap-module-source-map",
8
+ // Disable file watching in test mode
9
+ watchOptions: {
10
+ ignored: /node_modules/
11
+ }
12
+ }
13
+
14
+ const bundlerConfig =
15
+ config.bundler === "rspack" ? rspackTestConfig : baseConfig
16
+
17
+ module.exports = merge(baseConfig, bundlerConfig)
data/package/index.d.ts CHANGED
@@ -81,6 +81,20 @@ declare module 'shakapacker' {
81
81
  export * from 'webpack-merge'
82
82
  }
83
83
 
84
+ declare module 'shakapacker/rspack' {
85
+ import type { RspackOptions, RuleSetRule } from '@rspack/core'
86
+
87
+ export const config: Config
88
+ export function generateRspackConfig(extraConfig?: RspackOptions): RspackOptions
89
+ export const baseConfig: RspackOptions
90
+ export const env: Env
91
+ export const rules: RuleSetRule[]
92
+ export function moduleExists(packageName: string): boolean
93
+ export function canProcess<T = unknown>(rule: string, fn: (modulePath: string) => T): T | null
94
+ export const inliningCss: boolean
95
+ export * from 'webpack-merge'
96
+ }
97
+
84
98
  declare module 'shakapacker/package/babel/preset.js' {
85
99
  import { ConfigAPI, PluginItem, TransformOptions } from '@babel/core'
86
100
 
data/package/index.js CHANGED
@@ -4,9 +4,11 @@
4
4
  const webpackMerge = require("webpack-merge")
5
5
  const { resolve } = require("path")
6
6
  const { existsSync } = require("fs")
7
- const baseConfig = require("./environments/base")
8
- const rules = require("./rules")
9
7
  const config = require("./config")
8
+ const baseConfig = require("./environments/base")
9
+
10
+ const rulesPath = resolve(__dirname, "rules", `${config.bundler}.js`)
11
+ const rules = require(rulesPath)
10
12
  const devServer = require("./dev_server")
11
13
  const env = require("./env")
12
14
  const { moduleExists, canProcess } = require("./utils/helpers")
@@ -0,0 +1,25 @@
1
+ const { requireOrError } = require("../utils/requireOrError")
2
+
3
+ const { rspack } = requireOrError("@rspack/core")
4
+
5
+ const getOptimization = () => {
6
+ // Use Rspack's built-in minification instead of terser-webpack-plugin
7
+ const result = { minimize: true }
8
+ try {
9
+ result.minimizer = [
10
+ new rspack.SwcJsMinimizerRspackPlugin(),
11
+ new rspack.LightningCssMinimizerRspackPlugin()
12
+ ]
13
+ } catch (error) {
14
+ // eslint-disable-next-line no-console
15
+ console.warn(
16
+ "[SHAKAPACKER]: Warning: Could not configure Rspack minimizers:",
17
+ error.message
18
+ )
19
+ }
20
+ return result
21
+ }
22
+
23
+ module.exports = {
24
+ getOptimization
25
+ }