shakapacker 9.0.0.beta.0 → 9.0.0.beta.3
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/.github/workflows/claude-code-review.yml +54 -0
- data/.github/workflows/claude.yml +50 -0
- data/.github/workflows/dummy.yml +3 -3
- data/.github/workflows/test-bundlers.yml +152 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +15 -3
- data/CLAUDE.md +29 -0
- data/Gemfile.lock +1 -1
- data/README.md +42 -1
- data/Rakefile +39 -4
- data/TODO.md +51 -0
- data/TODO_v9.md +84 -0
- data/conductor-setup.sh +58 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/css-modules-export-mode.md +216 -86
- data/docs/deployment.md +10 -1
- data/docs/rspack.md +7 -7
- data/docs/rspack_migration_guide.md +202 -0
- data/docs/using_esbuild_loader.md +3 -3
- data/docs/using_swc_loader.md +5 -3
- data/docs/v6_upgrade.md +10 -0
- data/docs/v9_upgrade.md +185 -0
- data/lib/install/bin/shakapacker +3 -17
- data/lib/install/config/shakapacker.yml +9 -4
- data/lib/shakapacker/configuration.rb +75 -3
- data/lib/shakapacker/dev_server_runner.rb +19 -9
- data/lib/shakapacker/manifest.rb +4 -3
- data/lib/shakapacker/rspack_runner.rb +4 -42
- data/lib/shakapacker/runner.rb +105 -11
- data/lib/shakapacker/utils/manager.rb +2 -0
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +1 -1
- data/lib/shakapacker/webpack_runner.rb +4 -42
- data/lib/tasks/shakapacker/install.rake +6 -2
- data/package/config.js +24 -0
- data/package/environments/base.js +12 -2
- data/package/environments/development.js +52 -12
- data/package/environments/production.js +8 -3
- data/package/environments/test.js +5 -3
- data/package/index.d.ts +69 -30
- data/package/index.js +1 -1
- data/package/optimization/rspack.js +9 -5
- data/package/plugins/rspack.js +12 -28
- data/package/rspack/index.js +57 -0
- data/package/rules/babel.js +2 -2
- data/package/rules/esbuild.js +2 -2
- data/package/rules/raw.js +5 -5
- data/package/rules/rspack.js +77 -7
- data/package/rules/swc.js +2 -2
- data/package/utils/debug.js +49 -0
- data/package/utils/getStyleRule.js +19 -10
- data/package/utils/requireOrError.js +1 -1
- data/package/utils/validateCssModulesConfig.js +91 -0
- data/package/utils/validateDependencies.js +61 -0
- data/package/webpackDevServerConfig.js +2 -0
- data/package-lock.json +11966 -0
- data/package.json +9 -2
- data/test/package/rules/esbuild.test.js +1 -1
- data/test/package/rules/swc.test.js +1 -1
- data/tools/README.md +124 -0
- data/tools/css-modules-v9-codemod.js +179 -0
- data/yarn.lock +199 -81
- metadata +20 -3
- data/lib/install/bin/shakapacker-rspack +0 -13
data/package/index.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
declare module
|
2
|
-
import { Configuration, RuleSetRule } from
|
3
|
-
import * as https from
|
1
|
+
declare module "shakapacker" {
|
2
|
+
import { Configuration, RuleSetRule } from "webpack"
|
3
|
+
import * as https from "node:https"
|
4
4
|
|
5
5
|
export interface Config {
|
6
6
|
source_path: string
|
@@ -9,20 +9,29 @@ declare module 'shakapacker' {
|
|
9
9
|
css_extract_ignore_order_warnings: boolean
|
10
10
|
public_root_path: string
|
11
11
|
public_output_path: string
|
12
|
+
private_output_path?: string
|
12
13
|
cache_path: string
|
13
14
|
webpack_compile_output: boolean
|
14
15
|
shakapacker_precompile: boolean
|
15
16
|
additional_paths: string[]
|
16
17
|
cache_manifest: boolean
|
17
|
-
|
18
|
+
javascript_transpiler: string
|
18
19
|
ensure_consistent_versioning: boolean
|
19
20
|
compiler_strategy: string
|
20
21
|
useContentHash: boolean
|
21
|
-
compile: boolean
|
22
|
+
compile: boolean
|
22
23
|
outputPath: string
|
23
24
|
publicPath: string
|
24
25
|
publicPathWithoutCDN: string
|
25
26
|
manifestPath: string
|
27
|
+
manifest_path?: string
|
28
|
+
assets_bundler?: string
|
29
|
+
dev_server?: DevServerConfig
|
30
|
+
integrity?: {
|
31
|
+
enabled: boolean
|
32
|
+
cross_origin: string
|
33
|
+
hash_functions?: string[]
|
34
|
+
}
|
26
35
|
}
|
27
36
|
|
28
37
|
export interface Env {
|
@@ -33,9 +42,11 @@ declare module 'shakapacker' {
|
|
33
42
|
runningWebpackDevServer: boolean
|
34
43
|
}
|
35
44
|
|
36
|
-
type Header =
|
37
|
-
|
38
|
-
|
45
|
+
type Header =
|
46
|
+
| Array<{ key: string; value: string }>
|
47
|
+
| Record<string, string | string[]>
|
48
|
+
type ServerType = "http" | "https" | "spdy"
|
49
|
+
type WebSocketType = "sockjs" | "ws"
|
39
50
|
|
40
51
|
/**
|
41
52
|
* This has the same keys and behavior as https://webpack.js.org/configuration/dev-server/ except:
|
@@ -44,59 +55,87 @@ declare module 'shakapacker' {
|
|
44
55
|
* @see {import('webpack-dev-server').Configuration}
|
45
56
|
*/
|
46
57
|
interface DevServerConfig {
|
47
|
-
allowed_hosts?:
|
58
|
+
allowed_hosts?: "all" | "auto" | string | string[]
|
48
59
|
bonjour?: boolean | Record<string, unknown> // bonjour.BonjourOptions
|
49
60
|
client?: Record<string, unknown> // Client
|
50
61
|
compress?: boolean
|
51
62
|
dev_middleware?: Record<string, unknown> // webpackDevMiddleware.Options
|
52
63
|
headers?: Header | (() => Header)
|
53
64
|
history_api_fallback?: boolean | Record<string, unknown> // HistoryApiFallbackOptions
|
54
|
-
hmr?:
|
55
|
-
host?:
|
65
|
+
hmr?: "only" | boolean
|
66
|
+
host?: "local-ip" | "local-ipv4" | "local-ipv6" | string
|
56
67
|
http2?: boolean
|
57
68
|
https?: boolean | https.ServerOptions
|
58
69
|
ipc?: boolean | string
|
59
70
|
magic_html?: boolean
|
60
71
|
live_reload?: boolean
|
61
|
-
|
62
|
-
|
72
|
+
inline_css?: boolean
|
73
|
+
env_prefix?: string
|
74
|
+
open?:
|
75
|
+
| boolean
|
76
|
+
| string
|
77
|
+
| string[]
|
78
|
+
| Record<string, unknown>
|
79
|
+
| Record<string, unknown>[]
|
80
|
+
port?: "auto" | string | number
|
63
81
|
proxy?: unknown // ProxyConfigMap | ProxyConfigArray
|
64
82
|
setup_exit_signals?: boolean
|
65
83
|
static?: boolean | string | unknown // Static | Array<string | Static>
|
66
84
|
watch_files?: string | string[] | unknown // WatchFiles | Array<WatchFiles | string>
|
67
|
-
web_socket_server?:
|
68
|
-
|
85
|
+
web_socket_server?:
|
86
|
+
| string
|
87
|
+
| boolean
|
88
|
+
| WebSocketType
|
89
|
+
| {
|
90
|
+
type?: string | boolean | WebSocketType
|
91
|
+
options?: Record<string, unknown>
|
92
|
+
}
|
93
|
+
server?:
|
94
|
+
| string
|
95
|
+
| boolean
|
96
|
+
| ServerType
|
97
|
+
| { type?: string | boolean | ServerType; options?: https.ServerOptions }
|
69
98
|
[otherWebpackDevServerConfigKey: string]: unknown
|
70
99
|
}
|
71
100
|
|
72
101
|
export const config: Config
|
73
102
|
export const devServer: DevServerConfig
|
74
|
-
export function generateWebpackConfig(
|
103
|
+
export function generateWebpackConfig(
|
104
|
+
extraConfig?: Configuration
|
105
|
+
): Configuration
|
75
106
|
export const baseConfig: Configuration
|
76
107
|
export const env: Env
|
77
108
|
export const rules: RuleSetRule[]
|
78
109
|
export function moduleExists(packageName: string): boolean
|
79
|
-
export function canProcess<T = unknown>(
|
110
|
+
export function canProcess<T = unknown>(
|
111
|
+
rule: string,
|
112
|
+
fn: (modulePath: string) => T
|
113
|
+
): T | null
|
80
114
|
export const inliningCss: boolean
|
81
|
-
export * from
|
115
|
+
export * from "webpack-merge"
|
82
116
|
}
|
83
117
|
|
84
|
-
declare module
|
85
|
-
import type { RspackOptions
|
86
|
-
|
87
|
-
export const config: Config
|
88
|
-
export function generateRspackConfig(
|
118
|
+
declare module "shakapacker/rspack" {
|
119
|
+
import type { RspackOptions } from "@rspack/core"
|
120
|
+
|
121
|
+
export const config: import("shakapacker").Config
|
122
|
+
export function generateRspackConfig(
|
123
|
+
extraConfig?: RspackOptions
|
124
|
+
): RspackOptions
|
89
125
|
export const baseConfig: RspackOptions
|
90
|
-
export const env: Env
|
91
|
-
export const rules:
|
126
|
+
export const env: import("shakapacker").Env
|
127
|
+
export const rules: NonNullable<RspackOptions["module"]>["rules"]
|
92
128
|
export function moduleExists(packageName: string): boolean
|
93
|
-
export function canProcess<T = unknown>(
|
129
|
+
export function canProcess<T = unknown>(
|
130
|
+
rule: string,
|
131
|
+
fn: (modulePath: string) => T
|
132
|
+
): T | null
|
94
133
|
export const inliningCss: boolean
|
95
|
-
export * from
|
134
|
+
export * from "webpack-merge"
|
96
135
|
}
|
97
136
|
|
98
|
-
declare module
|
99
|
-
import { ConfigAPI, PluginItem, TransformOptions } from
|
137
|
+
declare module "shakapacker/package/babel/preset.js" {
|
138
|
+
import { ConfigAPI, PluginItem, TransformOptions } from "@babel/core"
|
100
139
|
|
101
140
|
interface RequiredTransformOptions {
|
102
141
|
plugins: PluginItem[]
|
@@ -108,4 +147,4 @@ declare module 'shakapacker/package/babel/preset.js' {
|
|
108
147
|
) => TransformOptions & RequiredTransformOptions
|
109
148
|
|
110
149
|
export = defaultConfigFunc
|
111
|
-
}
|
150
|
+
}
|
data/package/index.js
CHANGED
@@ -7,7 +7,7 @@ const { existsSync } = require("fs")
|
|
7
7
|
const config = require("./config")
|
8
8
|
const baseConfig = require("./environments/base")
|
9
9
|
|
10
|
-
const rulesPath = resolve(__dirname, "rules", `${config.
|
10
|
+
const rulesPath = resolve(__dirname, "rules", `${config.assets_bundler}.js`)
|
11
11
|
const rules = require(rulesPath)
|
12
12
|
const devServer = require("./dev_server")
|
13
13
|
const env = require("./env")
|
@@ -1,6 +1,7 @@
|
|
1
1
|
const { requireOrError } = require("../utils/requireOrError")
|
2
|
+
const { error: logError } = require("../utils/debug")
|
2
3
|
|
3
|
-
const
|
4
|
+
const rspack = requireOrError("@rspack/core")
|
4
5
|
|
5
6
|
const getOptimization = () => {
|
6
7
|
// Use Rspack's built-in minification instead of terser-webpack-plugin
|
@@ -11,10 +12,13 @@ const getOptimization = () => {
|
|
11
12
|
new rspack.LightningCssMinimizerRspackPlugin()
|
12
13
|
]
|
13
14
|
} catch (error) {
|
14
|
-
//
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
// Log full error with stack trace
|
16
|
+
logError(
|
17
|
+
`Failed to configure Rspack minimizers: ${error.message}\n${error.stack}`
|
18
|
+
)
|
19
|
+
// Re-throw the error to properly propagate it
|
20
|
+
throw new Error(
|
21
|
+
`Could not configure Rspack minimizers: ${error.message}. Please check that @rspack/core is properly installed.`
|
18
22
|
)
|
19
23
|
}
|
20
24
|
return result
|
data/package/plugins/rspack.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
const { existsSync, readFileSync } = require("fs")
|
2
1
|
const { requireOrError } = require("../utils/requireOrError")
|
3
2
|
|
4
3
|
const { RspackManifestPlugin } = requireOrError("rspack-manifest-plugin")
|
@@ -16,27 +15,7 @@ const getPlugins = () => {
|
|
16
15
|
writeToFileEmit: true,
|
17
16
|
// rspack-manifest-plugin uses different option names than webpack-assets-manifest
|
18
17
|
generate: (seed, files, entrypoints) => {
|
19
|
-
|
20
|
-
|
21
|
-
// Load existing manifest if it exists to handle concurrent builds
|
22
|
-
try {
|
23
|
-
if (existsSync(config.manifestPath)) {
|
24
|
-
const existingContent = readFileSync(config.manifestPath, "utf8")
|
25
|
-
const parsed = JSON.parse(existingContent)
|
26
|
-
if (parsed && typeof parsed === "object") {
|
27
|
-
manifest = {
|
28
|
-
...manifest,
|
29
|
-
...parsed
|
30
|
-
}
|
31
|
-
}
|
32
|
-
}
|
33
|
-
} catch (error) {
|
34
|
-
// eslint-disable-next-line no-console
|
35
|
-
console.warn(
|
36
|
-
"[SHAKAPACKER]: Warning: Could not read existing manifest.json:",
|
37
|
-
String(error)
|
38
|
-
)
|
39
|
-
}
|
18
|
+
const manifest = seed || {}
|
40
19
|
|
41
20
|
// Add files mapping first
|
42
21
|
files.forEach((file) => {
|
@@ -47,12 +26,17 @@ const getPlugins = () => {
|
|
47
26
|
const entrypointsManifest = {}
|
48
27
|
Object.entries(entrypoints).forEach(
|
49
28
|
([entrypointName, entrypointFiles]) => {
|
50
|
-
const jsFiles = entrypointFiles
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
29
|
+
const jsFiles = entrypointFiles
|
30
|
+
.filter(
|
31
|
+
(file) => file.endsWith(".js") && !file.includes(".hot-update.")
|
32
|
+
)
|
33
|
+
.map((file) => config.publicPathWithoutCDN + file)
|
34
|
+
const cssFiles = entrypointFiles
|
35
|
+
.filter(
|
36
|
+
(file) =>
|
37
|
+
file.endsWith(".css") && !file.includes(".hot-update.")
|
38
|
+
)
|
39
|
+
.map((file) => config.publicPathWithoutCDN + file)
|
56
40
|
|
57
41
|
entrypointsManifest[entrypointName] = {
|
58
42
|
assets: {
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/* eslint global-require: 0 */
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
3
|
+
|
4
|
+
const webpackMerge = require("webpack-merge")
|
5
|
+
const { resolve } = require("path")
|
6
|
+
const { existsSync } = require("fs")
|
7
|
+
const config = require("../config")
|
8
|
+
const baseConfig = require("../environments/base")
|
9
|
+
|
10
|
+
const rulesPath = resolve(__dirname, "../rules", "rspack.js")
|
11
|
+
const rules = require(rulesPath)
|
12
|
+
const devServer = require("../dev_server")
|
13
|
+
const env = require("../env")
|
14
|
+
const { moduleExists, canProcess } = require("../utils/helpers")
|
15
|
+
const inliningCss = require("../utils/inliningCss")
|
16
|
+
const { getPlugins } = require("../plugins/rspack")
|
17
|
+
const { getOptimization } = require("../optimization/rspack")
|
18
|
+
const { validateRspackDependencies } = require("../utils/validateDependencies")
|
19
|
+
|
20
|
+
const generateRspackConfig = (extraConfig = {}, ...extraArgs) => {
|
21
|
+
// Validate required dependencies first
|
22
|
+
validateRspackDependencies()
|
23
|
+
if (extraArgs.length > 0) {
|
24
|
+
throw new Error(
|
25
|
+
"Only one extra config may be passed here - use webpack-merge to merge configs before passing them to Shakapacker"
|
26
|
+
)
|
27
|
+
}
|
28
|
+
|
29
|
+
const { nodeEnv } = env
|
30
|
+
const path = resolve(__dirname, "../environments", `${nodeEnv}.js`)
|
31
|
+
const environmentConfig = existsSync(path) ? require(path) : baseConfig
|
32
|
+
|
33
|
+
// Create base rspack config
|
34
|
+
const rspackConfig = {
|
35
|
+
...environmentConfig,
|
36
|
+
module: {
|
37
|
+
rules
|
38
|
+
},
|
39
|
+
plugins: getPlugins(),
|
40
|
+
optimization: getOptimization()
|
41
|
+
}
|
42
|
+
|
43
|
+
return webpackMerge.merge({}, rspackConfig, extraConfig)
|
44
|
+
}
|
45
|
+
|
46
|
+
module.exports = {
|
47
|
+
config, // shakapacker.yml
|
48
|
+
devServer,
|
49
|
+
generateRspackConfig,
|
50
|
+
baseConfig,
|
51
|
+
env,
|
52
|
+
rules,
|
53
|
+
moduleExists,
|
54
|
+
canProcess,
|
55
|
+
inliningCss,
|
56
|
+
...webpackMerge
|
57
|
+
}
|
data/package/rules/babel.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
const { loaderMatches } = require("../utils/helpers")
|
2
|
-
const {
|
2
|
+
const { javascript_transpiler: javascriptTranspiler } = require("../config")
|
3
3
|
const { isProduction } = require("../env")
|
4
4
|
const jscommon = require("./jscommon")
|
5
5
|
|
6
|
-
module.exports = loaderMatches(
|
6
|
+
module.exports = loaderMatches(javascriptTranspiler, "babel", () => ({
|
7
7
|
test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
|
8
8
|
...jscommon,
|
9
9
|
use: [
|
data/package/rules/esbuild.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
const { loaderMatches } = require("../utils/helpers")
|
2
2
|
const { getEsbuildLoaderConfig } = require("../esbuild")
|
3
|
-
const {
|
3
|
+
const { javascript_transpiler: javascriptTranspiler } = require("../config")
|
4
4
|
const jscommon = require("./jscommon")
|
5
5
|
|
6
|
-
module.exports = loaderMatches(
|
6
|
+
module.exports = loaderMatches(javascriptTranspiler, "esbuild", () => ({
|
7
7
|
test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
|
8
8
|
...jscommon,
|
9
9
|
use: ({ resource }) => getEsbuildLoaderConfig(resource)
|
data/package/rules/raw.js
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
const config = require("../config")
|
2
2
|
|
3
|
-
const rspackRawConfig = {
|
3
|
+
const rspackRawConfig = () => ({
|
4
4
|
resourceQuery: /raw/,
|
5
5
|
type: "asset/source"
|
6
|
-
}
|
6
|
+
})
|
7
7
|
|
8
|
-
const webpackRawConfig = {
|
8
|
+
const webpackRawConfig = () => ({
|
9
9
|
test: /\.html$/,
|
10
10
|
exclude: /\.(js|mjs|jsx|ts|tsx)$/,
|
11
11
|
type: "asset/source"
|
12
|
-
}
|
12
|
+
})
|
13
13
|
|
14
14
|
module.exports =
|
15
|
-
config.
|
15
|
+
config.assets_bundler === "rspack" ? rspackRawConfig() : webpackRawConfig()
|
data/package/rules/rspack.js
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
/* eslint global-require: 0 */
|
2
2
|
|
3
3
|
const { moduleExists } = require("../utils/helpers")
|
4
|
+
const { debug, info, warn } = require("../utils/debug")
|
5
|
+
|
6
|
+
debug("Loading Rspack rules configuration...")
|
4
7
|
|
5
8
|
const rules = []
|
6
9
|
|
7
10
|
// Use Rspack's built-in SWC loader for JavaScript files
|
11
|
+
debug("Adding JavaScript rule with builtin:swc-loader")
|
8
12
|
rules.push({
|
9
13
|
test: /\.(js|jsx|mjs)$/,
|
10
14
|
exclude: /node_modules/,
|
15
|
+
// The 'type' field is required for Rspack to properly handle JavaScript modules
|
16
|
+
// when using builtin loaders. It ensures correct module parsing and transformation.
|
11
17
|
type: "javascript/auto",
|
12
18
|
use: [
|
13
19
|
{
|
@@ -30,9 +36,12 @@ rules.push({
|
|
30
36
|
})
|
31
37
|
|
32
38
|
// Use Rspack's built-in SWC loader for TypeScript files
|
39
|
+
debug("Adding TypeScript rule with builtin:swc-loader")
|
33
40
|
rules.push({
|
34
41
|
test: /\.(ts|tsx)$/,
|
35
42
|
exclude: /node_modules/,
|
43
|
+
// The 'type' field is required for Rspack to properly handle TypeScript modules
|
44
|
+
// when using builtin loaders. It ensures correct module parsing and transformation.
|
36
45
|
type: "javascript/auto",
|
37
46
|
use: [
|
38
47
|
{
|
@@ -55,42 +64,103 @@ rules.push({
|
|
55
64
|
})
|
56
65
|
|
57
66
|
// CSS rules using Rspack's built-in CSS handling
|
67
|
+
debug("Checking for CSS loader...")
|
58
68
|
if (moduleExists("css-loader")) {
|
69
|
+
debug("css-loader found, loading CSS rule configuration...")
|
59
70
|
const css = require("./css")
|
60
|
-
|
71
|
+
if (css) {
|
72
|
+
debug("Successfully added CSS rule")
|
73
|
+
rules.push(css)
|
74
|
+
} else {
|
75
|
+
warn("css-loader found but rule configuration returned null")
|
76
|
+
}
|
77
|
+
} else {
|
78
|
+
info("Skipping CSS support - css-loader not installed")
|
61
79
|
}
|
62
80
|
|
63
81
|
// Sass rules
|
82
|
+
debug("Checking for Sass loader...")
|
64
83
|
if (moduleExists("sass") && moduleExists("sass-loader")) {
|
84
|
+
debug("sass and sass-loader found, loading Sass rule configuration...")
|
65
85
|
const sass = require("./sass")
|
66
|
-
|
86
|
+
if (sass) {
|
87
|
+
debug("Successfully added Sass rule")
|
88
|
+
rules.push(sass)
|
89
|
+
} else {
|
90
|
+
warn("sass and sass-loader found but rule configuration returned null")
|
91
|
+
}
|
92
|
+
} else if (!moduleExists("sass")) {
|
93
|
+
info("Skipping Sass support - sass not installed")
|
94
|
+
} else if (!moduleExists("sass-loader")) {
|
95
|
+
info("Skipping Sass support - sass-loader not installed")
|
67
96
|
}
|
68
97
|
|
69
98
|
// Less rules
|
99
|
+
debug("Checking for Less loader...")
|
70
100
|
if (moduleExists("less") && moduleExists("less-loader")) {
|
101
|
+
debug("less and less-loader found, loading Less rule configuration...")
|
71
102
|
const less = require("./less")
|
72
|
-
|
103
|
+
if (less) {
|
104
|
+
debug("Successfully added Less rule")
|
105
|
+
rules.push(less)
|
106
|
+
} else {
|
107
|
+
warn("less and less-loader found but rule configuration returned null")
|
108
|
+
}
|
109
|
+
} else if (!moduleExists("less")) {
|
110
|
+
info("Skipping Less support - less not installed")
|
111
|
+
} else if (!moduleExists("less-loader")) {
|
112
|
+
info("Skipping Less support - less-loader not installed")
|
73
113
|
}
|
74
114
|
|
75
115
|
// Stylus rules
|
116
|
+
debug("Checking for Stylus loader...")
|
76
117
|
if (moduleExists("stylus") && moduleExists("stylus-loader")) {
|
118
|
+
debug("stylus and stylus-loader found, loading Stylus rule configuration...")
|
77
119
|
const stylus = require("./stylus")
|
78
|
-
|
120
|
+
if (stylus) {
|
121
|
+
debug("Successfully added Stylus rule")
|
122
|
+
rules.push(stylus)
|
123
|
+
} else {
|
124
|
+
warn("stylus and stylus-loader found but rule configuration returned null")
|
125
|
+
}
|
126
|
+
} else if (!moduleExists("stylus")) {
|
127
|
+
info("Skipping Stylus support - stylus not installed")
|
128
|
+
} else if (!moduleExists("stylus-loader")) {
|
129
|
+
info("Skipping Stylus support - stylus-loader not installed")
|
79
130
|
}
|
80
131
|
|
81
132
|
// ERB template support
|
133
|
+
debug("Checking for ERB template support...")
|
82
134
|
const erb = require("./erb")
|
83
135
|
|
84
|
-
|
136
|
+
if (erb) {
|
137
|
+
debug("Successfully added ERB rule")
|
138
|
+
rules.push(erb)
|
139
|
+
} else {
|
140
|
+
info("Skipping ERB support - rails-erb-loader not installed")
|
141
|
+
}
|
85
142
|
|
86
143
|
// File/asset handling using Rspack's built-in asset modules
|
144
|
+
debug("Adding file/asset handling rule...")
|
87
145
|
const file = require("./file")
|
88
146
|
|
89
|
-
|
147
|
+
if (file) {
|
148
|
+
debug("Successfully added file/asset rule")
|
149
|
+
rules.push(file)
|
150
|
+
} else {
|
151
|
+
warn("file rule configuration returned null")
|
152
|
+
}
|
90
153
|
|
91
154
|
// Raw file loading
|
155
|
+
debug("Adding raw file loading rule...")
|
92
156
|
const raw = require("./raw")
|
93
157
|
|
94
|
-
|
158
|
+
if (raw) {
|
159
|
+
debug("Successfully added raw file rule")
|
160
|
+
rules.push(raw)
|
161
|
+
} else {
|
162
|
+
warn("raw rule configuration returned null")
|
163
|
+
}
|
95
164
|
|
165
|
+
debug(`Rspack rules configuration complete. Total rules: ${rules.length}`)
|
96
166
|
module.exports = rules
|
data/package/rules/swc.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
const { loaderMatches } = require("../utils/helpers")
|
2
2
|
const { getSwcLoaderConfig } = require("../swc")
|
3
|
-
const {
|
3
|
+
const { javascript_transpiler: javascriptTranspiler } = require("../config")
|
4
4
|
const jscommon = require("./jscommon")
|
5
5
|
|
6
|
-
module.exports = loaderMatches(
|
6
|
+
module.exports = loaderMatches(javascriptTranspiler, "swc", () => ({
|
7
7
|
test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
|
8
8
|
...jscommon,
|
9
9
|
use: ({ resource }) => getSwcLoaderConfig(resource)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
/**
|
2
|
+
* Debug utility for Shakapacker
|
3
|
+
* Provides conditional logging based on environment variables
|
4
|
+
*/
|
5
|
+
|
6
|
+
const isDebugMode = () => {
|
7
|
+
// Explicitly check for debug mode being disabled
|
8
|
+
if (process.env.SHAKAPACKER_DEBUG === "false") {
|
9
|
+
return false
|
10
|
+
}
|
11
|
+
|
12
|
+
// Support both SHAKAPACKER_DEBUG (new) and DEBUG_SHAKAPACKER (legacy) for backwards compatibility
|
13
|
+
return (
|
14
|
+
process.env.SHAKAPACKER_DEBUG === "true" ||
|
15
|
+
process.env.DEBUG_SHAKAPACKER === "true"
|
16
|
+
)
|
17
|
+
}
|
18
|
+
|
19
|
+
const debug = (message, ...args) => {
|
20
|
+
if (isDebugMode()) {
|
21
|
+
// eslint-disable-next-line no-console
|
22
|
+
console.log(`[Shakapacker] ${message}`, ...args)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
const warn = (message, ...args) => {
|
27
|
+
// eslint-disable-next-line no-console
|
28
|
+
console.warn(`[Shakapacker] WARNING: ${message}`, ...args)
|
29
|
+
}
|
30
|
+
|
31
|
+
const error = (message, ...args) => {
|
32
|
+
// eslint-disable-next-line no-console
|
33
|
+
console.error(`[Shakapacker] ERROR: ${message}`, ...args)
|
34
|
+
}
|
35
|
+
|
36
|
+
const info = (message, ...args) => {
|
37
|
+
if (isDebugMode()) {
|
38
|
+
// eslint-disable-next-line no-console
|
39
|
+
console.info(`[Shakapacker] INFO: ${message}`, ...args)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
module.exports = {
|
44
|
+
debug,
|
45
|
+
warn,
|
46
|
+
error,
|
47
|
+
info,
|
48
|
+
isDebugMode
|
49
|
+
}
|
@@ -3,6 +3,7 @@ const { canProcess, moduleExists } = require("./helpers")
|
|
3
3
|
const { requireOrError } = require("./requireOrError")
|
4
4
|
const config = require("../config")
|
5
5
|
const inliningCss = require("./inliningCss")
|
6
|
+
const { validateCssModulesConfig } = require("./validateCssModulesConfig")
|
6
7
|
|
7
8
|
const getStyleRule = (test, preprocessors = []) => {
|
8
9
|
if (moduleExists("css-loader")) {
|
@@ -15,21 +16,29 @@ const getStyleRule = (test, preprocessors = []) => {
|
|
15
16
|
// style-loader is required when using css modules with HMR on the webpack-dev-server
|
16
17
|
|
17
18
|
const extractionPlugin =
|
18
|
-
config.
|
19
|
+
config.assets_bundler === "rspack"
|
19
20
|
? requireOrError("@rspack/core").CssExtractRspackPlugin.loader
|
20
21
|
: requireOrError("mini-css-extract-plugin").loader
|
21
22
|
|
23
|
+
const cssLoaderOptions = {
|
24
|
+
sourceMap: true,
|
25
|
+
importLoaders: 2,
|
26
|
+
modules: {
|
27
|
+
auto: true,
|
28
|
+
// v9 defaults: named exports with camelCase conversion
|
29
|
+
namedExport: true,
|
30
|
+
exportLocalsConvention: "camelCase"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
// Validate CSS modules configuration
|
35
|
+
validateCssModulesConfig(cssLoaderOptions)
|
36
|
+
|
22
37
|
const use = [
|
23
38
|
inliningCss ? "style-loader" : extractionPlugin,
|
24
39
|
{
|
25
40
|
loader: require.resolve("css-loader"),
|
26
|
-
options:
|
27
|
-
sourceMap: true,
|
28
|
-
importLoaders: 2,
|
29
|
-
modules: {
|
30
|
-
auto: true
|
31
|
-
}
|
32
|
-
}
|
41
|
+
options: cssLoaderOptions
|
33
42
|
},
|
34
43
|
tryPostcss(),
|
35
44
|
...preprocessors
|
@@ -40,8 +49,8 @@ const getStyleRule = (test, preprocessors = []) => {
|
|
40
49
|
use
|
41
50
|
}
|
42
51
|
|
43
|
-
if (config.
|
44
|
-
result.type = "javascript/auto"
|
52
|
+
if (config.assets_bundler === "rspack") {
|
53
|
+
result.type = "javascript/auto"
|
45
54
|
}
|
46
55
|
|
47
56
|
return result
|
@@ -7,7 +7,7 @@ const requireOrError = (moduleName) => {
|
|
7
7
|
return require(moduleName)
|
8
8
|
} catch (error) {
|
9
9
|
throw new Error(
|
10
|
-
`[SHAKAPACKER]: ${moduleName} is required for ${config.
|
10
|
+
`[SHAKAPACKER]: ${moduleName} is required for ${config.assets_bundler} but is not installed. View Shakapacker's documented dependencies at https://github.com/shakacode/shakapacker/tree/main/docs/peer-dependencies.md`
|
11
11
|
)
|
12
12
|
}
|
13
13
|
}
|