shakapacker 8.4.0 → 9.0.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/.eslintignore +1 -0
- data/.eslintrc.fast.js +40 -0
- data/.eslintrc.js +48 -0
- data/.github/STATUS.md +1 -0
- data/.github/workflows/claude-code-review.yml +54 -0
- data/.github/workflows/claude.yml +50 -0
- data/.github/workflows/dummy.yml +8 -4
- data/.github/workflows/generator.yml +17 -14
- data/.github/workflows/node.yml +23 -1
- data/.github/workflows/ruby.yml +11 -0
- data/.github/workflows/test-bundlers.yml +170 -0
- data/.gitignore +17 -0
- data/.husky/pre-commit +2 -0
- data/.npmignore +56 -0
- data/.prettierignore +3 -0
- data/.rubocop.yml +1 -0
- data/.yalcignore +26 -0
- data/CHANGELOG.md +156 -18
- data/CLAUDE.md +29 -0
- data/CONTRIBUTING.md +138 -20
- data/Gemfile.lock +3 -3
- data/README.md +130 -5
- data/Rakefile +39 -4
- data/TODO.md +50 -0
- data/TODO_v9.md +87 -0
- data/conductor-setup.sh +70 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/css-modules-export-mode.md +512 -0
- data/docs/deployment.md +10 -1
- data/docs/optional-peer-dependencies.md +198 -0
- data/docs/peer-dependencies.md +60 -0
- data/docs/rspack.md +190 -0
- data/docs/rspack_migration_guide.md +202 -0
- data/docs/transpiler-migration.md +188 -0
- data/docs/transpiler-performance.md +179 -0
- data/docs/troubleshooting.md +5 -0
- data/docs/typescript-migration.md +378 -0
- data/docs/typescript.md +99 -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 +413 -0
- data/lib/install/bin/shakapacker +3 -5
- data/lib/install/config/rspack/rspack.config.js +6 -0
- data/lib/install/config/rspack/rspack.config.ts +7 -0
- data/lib/install/config/shakapacker.yml +12 -2
- data/lib/install/config/webpack/webpack.config.ts +7 -0
- data/lib/install/package.json +38 -0
- data/lib/install/template.rb +194 -44
- data/lib/shakapacker/configuration.rb +141 -0
- data/lib/shakapacker/dev_server_runner.rb +25 -5
- data/lib/shakapacker/doctor.rb +844 -0
- data/lib/shakapacker/manifest.rb +4 -2
- data/lib/shakapacker/rspack_runner.rb +19 -0
- data/lib/shakapacker/runner.rb +144 -4
- data/lib/shakapacker/swc_migrator.rb +376 -0
- 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/shakapacker.rb +2 -1
- data/lib/tasks/shakapacker/doctor.rake +8 -0
- data/lib/tasks/shakapacker/install.rake +12 -2
- data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
- data/lib/tasks/shakapacker.rake +1 -0
- data/package/.npmignore +4 -0
- data/package/babel/preset.ts +56 -0
- data/package/config.ts +175 -0
- data/package/{dev_server.js → dev_server.ts} +8 -5
- data/package/env.ts +92 -0
- data/package/environments/base.ts +138 -0
- data/package/environments/development.ts +90 -0
- data/package/environments/production.ts +80 -0
- data/package/environments/test.ts +53 -0
- data/package/environments/types.ts +90 -0
- data/package/esbuild/index.ts +42 -0
- data/package/index.d.ts +3 -97
- data/package/index.ts +52 -0
- data/package/loaders.d.ts +28 -0
- data/package/optimization/rspack.ts +36 -0
- data/package/optimization/webpack.ts +57 -0
- data/package/plugins/rspack.ts +103 -0
- data/package/plugins/webpack.ts +62 -0
- data/package/rspack/index.ts +64 -0
- data/package/rules/{babel.js → babel.ts} +2 -2
- data/package/rules/{coffee.js → coffee.ts} +1 -1
- data/package/rules/css.ts +3 -0
- data/package/rules/{erb.js → erb.ts} +1 -1
- data/package/rules/esbuild.ts +10 -0
- data/package/rules/file.ts +40 -0
- data/package/rules/{jscommon.js → jscommon.ts} +4 -4
- data/package/rules/{less.js → less.ts} +4 -4
- data/package/rules/raw.ts +25 -0
- data/package/rules/rspack.ts +176 -0
- data/package/rules/{sass.js → sass.ts} +7 -3
- data/package/rules/{stylus.js → stylus.ts} +4 -8
- data/package/rules/swc.ts +10 -0
- data/package/rules/{index.js → webpack.ts} +1 -1
- data/package/swc/index.ts +54 -0
- data/package/types/README.md +87 -0
- data/package/types/index.ts +60 -0
- data/package/types.ts +108 -0
- data/package/utils/configPath.ts +6 -0
- data/package/utils/debug.ts +49 -0
- data/package/utils/defaultConfigPath.ts +4 -0
- data/package/utils/errorCodes.ts +219 -0
- data/package/utils/errorHelpers.ts +143 -0
- data/package/utils/getStyleRule.ts +64 -0
- data/package/utils/helpers.ts +85 -0
- data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
- data/package/utils/pathValidation.ts +139 -0
- data/package/utils/requireOrError.ts +15 -0
- data/package/utils/snakeToCamelCase.ts +5 -0
- data/package/utils/typeGuards.ts +342 -0
- data/package/utils/validateDependencies.ts +61 -0
- data/package/webpack-types.d.ts +33 -0
- data/package/webpackDevServerConfig.ts +117 -0
- data/package.json +134 -9
- data/scripts/remove-use-strict.js +45 -0
- data/scripts/type-check-no-emit.js +27 -0
- data/test/package/config.test.js +3 -0
- data/test/package/env.test.js +42 -7
- data/test/package/environments/base.test.js +5 -1
- data/test/package/rules/babel.test.js +16 -0
- data/test/package/rules/esbuild.test.js +1 -1
- data/test/package/rules/raw.test.js +40 -7
- data/test/package/rules/swc.test.js +1 -1
- data/test/package/rules/webpack.test.js +35 -0
- data/test/package/staging.test.js +4 -3
- data/test/package/transpiler-defaults.test.js +127 -0
- data/test/peer-dependencies.sh +85 -0
- data/test/scripts/remove-use-strict.test.js +125 -0
- data/test/typescript/build.test.js +118 -0
- data/test/typescript/environments.test.js +107 -0
- data/test/typescript/pathValidation.test.js +142 -0
- data/test/typescript/securityValidation.test.js +182 -0
- data/tools/README.md +124 -0
- data/tools/css-modules-v9-codemod.js +179 -0
- data/tsconfig.eslint.json +16 -0
- data/tsconfig.json +38 -0
- data/yarn.lock +2704 -767
- metadata +111 -41
- data/package/babel/preset.js +0 -48
- data/package/config.js +0 -56
- data/package/env.js +0 -48
- data/package/environments/base.js +0 -171
- data/package/environments/development.js +0 -13
- data/package/environments/production.js +0 -88
- data/package/environments/test.js +0 -3
- data/package/esbuild/index.js +0 -40
- data/package/index.js +0 -40
- data/package/rules/css.js +0 -3
- data/package/rules/esbuild.js +0 -10
- data/package/rules/file.js +0 -29
- data/package/rules/raw.js +0 -5
- data/package/rules/swc.js +0 -10
- data/package/swc/index.js +0 -50
- data/package/utils/configPath.js +0 -4
- data/package/utils/defaultConfigPath.js +0 -2
- data/package/utils/getStyleRule.js +0 -40
- data/package/utils/helpers.js +0 -62
- data/package/utils/snakeToCamelCase.js +0 -5
- data/package/webpackDevServerConfig.js +0 -71
- data/test/package/rules/index.test.js +0 -16
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { requireOrError } = require("../utils/requireOrError")
|
|
2
|
+
// TODO: Change to `const { WebpackAssetsManifest }` when dropping 'webpack-assets-manifest < 6.0.0' (Node >=20.10.0) support
|
|
3
|
+
const WebpackAssetsManifest = requireOrError("webpack-assets-manifest")
|
|
4
|
+
const webpack = requireOrError("webpack")
|
|
5
|
+
const config = require("../config")
|
|
6
|
+
const { isProduction } = require("../env")
|
|
7
|
+
const { moduleExists } = require("../utils/helpers")
|
|
8
|
+
|
|
9
|
+
const getPlugins = (): unknown[] => {
|
|
10
|
+
// TODO: Remove WebpackAssetsManifestConstructor workaround when dropping 'webpack-assets-manifest < 6.0.0' (Node >=20.10.0) support
|
|
11
|
+
const WebpackAssetsManifestConstructor =
|
|
12
|
+
"WebpackAssetsManifest" in WebpackAssetsManifest
|
|
13
|
+
? WebpackAssetsManifest.WebpackAssetsManifest
|
|
14
|
+
: WebpackAssetsManifest
|
|
15
|
+
const plugins = [
|
|
16
|
+
new webpack.EnvironmentPlugin(process.env),
|
|
17
|
+
new WebpackAssetsManifestConstructor({
|
|
18
|
+
entrypoints: true,
|
|
19
|
+
writeToDisk: true,
|
|
20
|
+
output: config.manifestPath,
|
|
21
|
+
entrypointsUseAssets: true,
|
|
22
|
+
publicPath: config.publicPathWithoutCDN,
|
|
23
|
+
integrity: config.integrity.enabled,
|
|
24
|
+
integrityHashes: config.integrity.hash_functions
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
if (moduleExists("css-loader") && moduleExists("mini-css-extract-plugin")) {
|
|
29
|
+
const hash = isProduction || config.useContentHash ? "-[contenthash:8]" : ""
|
|
30
|
+
const MiniCssExtractPlugin = requireOrError("mini-css-extract-plugin")
|
|
31
|
+
plugins.push(
|
|
32
|
+
new MiniCssExtractPlugin({
|
|
33
|
+
filename: `css/[name]${hash}.css`,
|
|
34
|
+
chunkFilename: `css/[id]${hash}.css`,
|
|
35
|
+
// For projects where css ordering has been mitigated through consistent use of scoping or naming conventions,
|
|
36
|
+
// the css order warnings can be disabled by setting the ignoreOrder flag.
|
|
37
|
+
ignoreOrder: config.css_extract_ignore_order_warnings
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
config.integrity.enabled &&
|
|
44
|
+
moduleExists("webpack-subresource-integrity")
|
|
45
|
+
) {
|
|
46
|
+
const SubresourceIntegrityPlugin = requireOrError(
|
|
47
|
+
"webpack-subresource-integrity"
|
|
48
|
+
)
|
|
49
|
+
plugins.push(
|
|
50
|
+
new SubresourceIntegrityPlugin({
|
|
51
|
+
hashFuncNames: config.integrity.hash_functions,
|
|
52
|
+
enabled: isProduction
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return plugins
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export = {
|
|
61
|
+
getPlugins
|
|
62
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* eslint global-require: 0 */
|
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
|
3
|
+
|
|
4
|
+
// Mixed require/import syntax:
|
|
5
|
+
// - Using require() for compiled JS modules that may not have proper ES module exports
|
|
6
|
+
// - Using import for type-only imports and Node.js built-in modules
|
|
7
|
+
const webpackMerge = require("webpack-merge")
|
|
8
|
+
import { resolve } from "path"
|
|
9
|
+
import { existsSync } from "fs"
|
|
10
|
+
import type { RspackConfigWithDevServer } from "../environments/types"
|
|
11
|
+
const config = require("../config")
|
|
12
|
+
const baseConfig = require("../environments/base")
|
|
13
|
+
const devServer = require("../dev_server")
|
|
14
|
+
const env = require("../env")
|
|
15
|
+
const { moduleExists, canProcess } = require("../utils/helpers")
|
|
16
|
+
const inliningCss = require("../utils/inliningCss")
|
|
17
|
+
const { getPlugins } = require("../plugins/rspack")
|
|
18
|
+
const { getOptimization } = require("../optimization/rspack")
|
|
19
|
+
const { validateRspackDependencies } = require("../utils/validateDependencies")
|
|
20
|
+
|
|
21
|
+
const rulesPath = resolve(__dirname, "../rules", "rspack.js")
|
|
22
|
+
const rules = require(rulesPath)
|
|
23
|
+
|
|
24
|
+
const generateRspackConfig = (extraConfig: RspackConfigWithDevServer = {}, ...extraArgs: unknown[]): RspackConfigWithDevServer => {
|
|
25
|
+
// Validate required dependencies first
|
|
26
|
+
validateRspackDependencies()
|
|
27
|
+
if (extraArgs.length > 0) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
"Only one extra config may be passed here - use webpack-merge to merge configs before passing them to Shakapacker"
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const { nodeEnv } = env
|
|
34
|
+
const path = resolve(__dirname, "../environments", `${nodeEnv}.js`)
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
|
+
const environmentConfig = existsSync(path) ? require(path) : baseConfig
|
|
37
|
+
|
|
38
|
+
// Create base rspack config
|
|
39
|
+
const rspackConfig: RspackConfigWithDevServer = {
|
|
40
|
+
...environmentConfig,
|
|
41
|
+
module: {
|
|
42
|
+
rules
|
|
43
|
+
},
|
|
44
|
+
plugins: getPlugins(),
|
|
45
|
+
optimization: getOptimization()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return webpackMerge.merge({}, rspackConfig, extraConfig)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Re-export webpack-merge utilities for backward compatibility
|
|
52
|
+
export { merge, mergeWithCustomize, mergeWithRules, unique } from "webpack-merge"
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
config, // shakapacker.yml
|
|
56
|
+
devServer,
|
|
57
|
+
generateRspackConfig,
|
|
58
|
+
baseConfig,
|
|
59
|
+
env,
|
|
60
|
+
rules,
|
|
61
|
+
moduleExists,
|
|
62
|
+
canProcess,
|
|
63
|
+
inliningCss
|
|
64
|
+
}
|
|
@@ -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
|
-
|
|
6
|
+
export = loaderMatches(javascriptTranspiler, "babel", () => ({
|
|
7
7
|
test: /\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/,
|
|
8
8
|
...jscommon,
|
|
9
9
|
use: [
|
|
@@ -2,7 +2,7 @@ const { canProcess } = require("../utils/helpers")
|
|
|
2
2
|
|
|
3
3
|
const runner = /^win/.test(process.platform) ? "ruby " : ""
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
export = canProcess("rails-erb-loader", (resolvedPath: string) => ({
|
|
6
6
|
test: /\.erb$/,
|
|
7
7
|
enforce: "pre",
|
|
8
8
|
exclude: /node_modules/,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { loaderMatches } = require("../utils/helpers")
|
|
2
|
+
const { getEsbuildLoaderConfig } = require("../esbuild")
|
|
3
|
+
const { javascript_transpiler: javascriptTranspiler } = require("../config")
|
|
4
|
+
const jscommon = require("./jscommon")
|
|
5
|
+
|
|
6
|
+
export = loaderMatches(javascriptTranspiler, "esbuild", () => ({
|
|
7
|
+
test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
|
|
8
|
+
...jscommon,
|
|
9
|
+
use: ({ resource }: { resource: string }) => getEsbuildLoaderConfig(resource)
|
|
10
|
+
}))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { dirname, sep, normalize } from "path"
|
|
2
|
+
const {
|
|
3
|
+
additional_paths: additionalPaths,
|
|
4
|
+
source_path: sourcePath
|
|
5
|
+
} = require("../config")
|
|
6
|
+
|
|
7
|
+
export = {
|
|
8
|
+
test: /\.(bmp|gif|jpe?g|png|tiff|ico|avif|webp|eot|otf|ttf|woff|woff2|svg)$/,
|
|
9
|
+
exclude: /\.(js|mjs|jsx|ts|tsx)$/,
|
|
10
|
+
type: "asset/resource",
|
|
11
|
+
generator: {
|
|
12
|
+
filename: (pathData: { filename?: string }) => {
|
|
13
|
+
// Guard against null/undefined pathData or filename
|
|
14
|
+
if (!pathData || !pathData.filename) {
|
|
15
|
+
return `static/[name]-[hash][ext][query]`
|
|
16
|
+
}
|
|
17
|
+
const path = normalize(dirname(pathData.filename))
|
|
18
|
+
const stripPaths = [...additionalPaths, sourcePath].map((p: string) =>
|
|
19
|
+
normalize(p)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const selectedStripPath = stripPaths.find((includePath: string) =>
|
|
23
|
+
path.startsWith(includePath)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if (!selectedStripPath) {
|
|
27
|
+
return `static/[name]-[hash][ext][query]`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Split on both forward and backward slashes for cross-platform compatibility
|
|
31
|
+
const folders = path
|
|
32
|
+
.replace(selectedStripPath, "")
|
|
33
|
+
.split(/[\\/]/)
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
|
|
36
|
+
const foldersWithStatic = ["static", ...folders].join("/")
|
|
37
|
+
return `${foldersWithStatic}/[name]-[hash][ext][query]`
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { resolve } from "path"
|
|
2
|
+
import { realpathSync } from "fs"
|
|
3
3
|
const {
|
|
4
4
|
source_path: sourcePath,
|
|
5
5
|
additional_paths: additionalPaths
|
|
6
6
|
} = require("../config")
|
|
7
7
|
|
|
8
|
-
const inclusions = [sourcePath, ...additionalPaths].map((p) => {
|
|
8
|
+
const inclusions = [sourcePath, ...additionalPaths].map((p: string) => {
|
|
9
9
|
try {
|
|
10
10
|
return realpathSync(p)
|
|
11
11
|
} catch (e) {
|
|
@@ -13,7 +13,7 @@ const inclusions = [sourcePath, ...additionalPaths].map((p) => {
|
|
|
13
13
|
}
|
|
14
14
|
})
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
export = {
|
|
17
17
|
include: inclusions,
|
|
18
18
|
exclude: [
|
|
19
19
|
{
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
const path = require("path")
|
|
2
1
|
const { canProcess } = require("../utils/helpers")
|
|
3
|
-
const getStyleRule = require("../utils/getStyleRule")
|
|
2
|
+
const { getStyleRule } = require("../utils/getStyleRule")
|
|
4
3
|
|
|
5
4
|
const {
|
|
6
5
|
additional_paths: paths,
|
|
7
6
|
source_path: sourcePath
|
|
8
7
|
} = require("../config")
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
export = canProcess("less-loader", (resolvedPath: string) =>
|
|
11
10
|
getStyleRule(/\.(less)(\.erb)?$/i, [
|
|
12
11
|
{
|
|
13
12
|
loader: resolvedPath,
|
|
14
13
|
options: {
|
|
15
14
|
lessOptions: {
|
|
16
|
-
paths
|
|
15
|
+
// Additional paths for Less imports (node_modules is resolved automatically)
|
|
16
|
+
paths: [sourcePath, ...paths]
|
|
17
17
|
},
|
|
18
18
|
sourceMap: true
|
|
19
19
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const config = require("../config")
|
|
2
|
+
|
|
3
|
+
const rspackRawConfig = () => ({
|
|
4
|
+
resourceQuery: /raw/,
|
|
5
|
+
type: "asset/source"
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const webpackRawConfig = () => ({
|
|
9
|
+
oneOf: [
|
|
10
|
+
{
|
|
11
|
+
// Match any file with ?raw query parameter
|
|
12
|
+
resourceQuery: /raw/,
|
|
13
|
+
type: "asset/source"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
// Fallback: match .html files without query
|
|
17
|
+
test: /\.html$/,
|
|
18
|
+
exclude: /\.(js|mjs|jsx|ts|tsx)$/,
|
|
19
|
+
type: "asset/source"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export =
|
|
25
|
+
config.assets_bundler === "rspack" ? rspackRawConfig() : webpackRawConfig()
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/* eslint global-require: 0 */
|
|
2
|
+
|
|
3
|
+
const { moduleExists } = require("../utils/helpers")
|
|
4
|
+
const { debug, info, warn } = require("../utils/debug")
|
|
5
|
+
|
|
6
|
+
debug("Loading Rspack rules configuration...")
|
|
7
|
+
|
|
8
|
+
const rules = []
|
|
9
|
+
|
|
10
|
+
// Use Rspack's built-in SWC loader for JavaScript files
|
|
11
|
+
debug("Adding JavaScript rule with builtin:swc-loader")
|
|
12
|
+
rules.push({
|
|
13
|
+
test: /\.(js|jsx|mjs)$/,
|
|
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.
|
|
17
|
+
type: "javascript/auto",
|
|
18
|
+
use: [
|
|
19
|
+
{
|
|
20
|
+
loader: "builtin:swc-loader",
|
|
21
|
+
options: {
|
|
22
|
+
jsc: {
|
|
23
|
+
parser: {
|
|
24
|
+
syntax: "ecmascript",
|
|
25
|
+
jsx: true
|
|
26
|
+
},
|
|
27
|
+
transform: {
|
|
28
|
+
react: {
|
|
29
|
+
runtime: "automatic"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Use Rspack's built-in SWC loader for TypeScript files
|
|
39
|
+
debug("Adding TypeScript rule with builtin:swc-loader")
|
|
40
|
+
rules.push({
|
|
41
|
+
test: /\.(ts|tsx)$/,
|
|
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.
|
|
45
|
+
type: "javascript/auto",
|
|
46
|
+
use: [
|
|
47
|
+
{
|
|
48
|
+
loader: "builtin:swc-loader",
|
|
49
|
+
options: {
|
|
50
|
+
jsc: {
|
|
51
|
+
parser: {
|
|
52
|
+
syntax: "typescript",
|
|
53
|
+
tsx: true
|
|
54
|
+
},
|
|
55
|
+
transform: {
|
|
56
|
+
react: {
|
|
57
|
+
runtime: "automatic"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// CSS rules using Rspack's built-in CSS handling
|
|
67
|
+
debug("Checking for CSS loader...")
|
|
68
|
+
if (moduleExists("css-loader")) {
|
|
69
|
+
debug("css-loader found, loading CSS rule configuration...")
|
|
70
|
+
const css = require("./css")
|
|
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")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Sass rules
|
|
82
|
+
debug("Checking for Sass loader...")
|
|
83
|
+
if (moduleExists("sass") && moduleExists("sass-loader")) {
|
|
84
|
+
debug("sass and sass-loader found, loading Sass rule configuration...")
|
|
85
|
+
const sass = require("./sass")
|
|
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")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Less rules
|
|
99
|
+
debug("Checking for Less loader...")
|
|
100
|
+
if (moduleExists("less") && moduleExists("less-loader")) {
|
|
101
|
+
debug("less and less-loader found, loading Less rule configuration...")
|
|
102
|
+
const less = require("./less")
|
|
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")
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Stylus rules
|
|
116
|
+
debug("Checking for Stylus loader...")
|
|
117
|
+
if (moduleExists("stylus") && moduleExists("stylus-loader")) {
|
|
118
|
+
debug("stylus and stylus-loader found, loading Stylus rule configuration...")
|
|
119
|
+
const stylus = require("./stylus")
|
|
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")
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ERB template support
|
|
133
|
+
debug("Checking for ERB template support...")
|
|
134
|
+
const erb = require("./erb")
|
|
135
|
+
|
|
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
|
+
}
|
|
142
|
+
|
|
143
|
+
// File/asset handling using Rspack's built-in asset modules
|
|
144
|
+
// This is a critical rule required for proper asset handling
|
|
145
|
+
debug("Adding file/asset handling rule...")
|
|
146
|
+
const file = require("./file")
|
|
147
|
+
|
|
148
|
+
if (!file) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
"CRITICAL: file rule configuration returned null. " +
|
|
151
|
+
"Asset handling is required for proper bundling. " +
|
|
152
|
+
"Please ensure the file rule module exports a valid rule configuration."
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
debug("Successfully added file/asset rule")
|
|
157
|
+
rules.push(file)
|
|
158
|
+
|
|
159
|
+
// Raw file loading
|
|
160
|
+
// This is a critical rule required for raw file imports
|
|
161
|
+
debug("Adding raw file loading rule...")
|
|
162
|
+
const raw = require("./raw")
|
|
163
|
+
|
|
164
|
+
if (!raw) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
"CRITICAL: raw rule configuration returned null. " +
|
|
167
|
+
"Raw file loading is required for proper bundling. " +
|
|
168
|
+
"Please ensure the raw rule module exports a valid rule configuration."
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
debug("Successfully added raw file rule")
|
|
173
|
+
rules.push(raw)
|
|
174
|
+
|
|
175
|
+
debug(`Rspack rules configuration complete. Total rules: ${rules.length}`)
|
|
176
|
+
export = rules
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
/* eslint global-require: 0 */
|
|
2
2
|
|
|
3
|
-
const getStyleRule = require("../utils/getStyleRule")
|
|
3
|
+
const { getStyleRule } = require("../utils/getStyleRule")
|
|
4
4
|
const { canProcess, packageMajorVersion } = require("../utils/helpers")
|
|
5
5
|
const { additional_paths: extraPaths } = require("../config")
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export = canProcess("sass-loader", (resolvedPath: string) => {
|
|
8
8
|
const optionKey =
|
|
9
9
|
packageMajorVersion("sass-loader") > 15 ? "loadPaths" : "includePaths"
|
|
10
10
|
return getStyleRule(/\.(scss|sass)(\.erb)?$/i, [
|
|
11
11
|
{
|
|
12
12
|
loader: resolvedPath,
|
|
13
13
|
options: {
|
|
14
|
-
|
|
14
|
+
sourceMap: true,
|
|
15
|
+
sassOptions: {
|
|
16
|
+
[optionKey]: extraPaths,
|
|
17
|
+
quietDeps: true
|
|
18
|
+
}
|
|
15
19
|
}
|
|
16
20
|
}
|
|
17
21
|
])
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
const path = require("path")
|
|
2
1
|
const { canProcess } = require("../utils/helpers")
|
|
3
|
-
const getStyleRule = require("../utils/getStyleRule")
|
|
2
|
+
const { getStyleRule } = require("../utils/getStyleRule")
|
|
4
3
|
|
|
5
4
|
const {
|
|
6
5
|
additional_paths: paths,
|
|
7
6
|
source_path: sourcePath
|
|
8
7
|
} = require("../config")
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
export = canProcess("stylus-loader", (resolvedPath: string) =>
|
|
11
10
|
getStyleRule(/\.(styl(us)?)(\.erb)?$/i, [
|
|
12
11
|
{
|
|
13
12
|
loader: resolvedPath,
|
|
14
13
|
options: {
|
|
15
14
|
stylusOptions: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
sourcePath,
|
|
19
|
-
...paths
|
|
20
|
-
]
|
|
15
|
+
// Additional paths for Stylus imports (node_modules is resolved automatically)
|
|
16
|
+
include: [sourcePath, ...paths]
|
|
21
17
|
},
|
|
22
18
|
sourceMap: true
|
|
23
19
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { loaderMatches } = require("../utils/helpers")
|
|
2
|
+
const { getSwcLoaderConfig } = require("../swc")
|
|
3
|
+
const { javascript_transpiler: javascriptTranspiler } = require("../config")
|
|
4
|
+
const jscommon = require("./jscommon")
|
|
5
|
+
|
|
6
|
+
export = loaderMatches(javascriptTranspiler, "swc", () => ({
|
|
7
|
+
test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
|
|
8
|
+
...jscommon,
|
|
9
|
+
use: ({ resource }: { resource: string }) => getSwcLoaderConfig(resource)
|
|
10
|
+
}))
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* eslint global-require: 0 */
|
|
2
|
+
/* eslint import/no-dynamic-require: 0 */
|
|
3
|
+
|
|
4
|
+
import { resolve } from "path"
|
|
5
|
+
import { existsSync } from "fs"
|
|
6
|
+
import { merge } from "webpack-merge"
|
|
7
|
+
import type { RuleSetRule } from "webpack"
|
|
8
|
+
|
|
9
|
+
const JSX_FILE_REGEX = /\.(jsx|tsx)(\.erb)?$/
|
|
10
|
+
const TYPESCRIPT_FILE_REGEX = /\.(ts|tsx)(\.erb)?$/
|
|
11
|
+
|
|
12
|
+
const isJsxFile = (filename: string): boolean => !!filename.match(JSX_FILE_REGEX)
|
|
13
|
+
|
|
14
|
+
const isTypescriptFile = (filename: string): boolean => !!filename.match(TYPESCRIPT_FILE_REGEX)
|
|
15
|
+
|
|
16
|
+
const getCustomConfig = (): Partial<RuleSetRule> => {
|
|
17
|
+
const path = resolve("config", "swc.config.js")
|
|
18
|
+
if (existsSync(path)) {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
20
|
+
return require(path)
|
|
21
|
+
}
|
|
22
|
+
return {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const getSwcLoaderConfig = (filenameToProcess: string): RuleSetRule => {
|
|
26
|
+
const customConfig = getCustomConfig()
|
|
27
|
+
const isTs = isTypescriptFile(filenameToProcess)
|
|
28
|
+
const isJsx = isJsxFile(filenameToProcess)
|
|
29
|
+
const jsxKey = isTs ? "tsx" : "jsx"
|
|
30
|
+
|
|
31
|
+
const defaultConfig: RuleSetRule = {
|
|
32
|
+
loader: require.resolve("swc-loader"),
|
|
33
|
+
options: {
|
|
34
|
+
jsc: {
|
|
35
|
+
parser: {
|
|
36
|
+
dynamicImport: true,
|
|
37
|
+
syntax: isTs ? "typescript" : "ecmascript",
|
|
38
|
+
[jsxKey]: isJsx
|
|
39
|
+
},
|
|
40
|
+
loose: true
|
|
41
|
+
},
|
|
42
|
+
sourceMaps: true,
|
|
43
|
+
env: {
|
|
44
|
+
coreJs: 3,
|
|
45
|
+
exclude: ["transform-typeof-symbol"],
|
|
46
|
+
mode: "entry"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return merge(defaultConfig, customConfig)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { getSwcLoaderConfig }
|