shakapacker 8.0.2 → 9.2.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 +9 -4
- data/.github/workflows/generator.yml +32 -10
- data/.github/workflows/node.yml +23 -1
- data/.github/workflows/ruby.yml +33 -2
- data/.github/workflows/test-bundlers.yml +170 -0
- data/.gitignore +20 -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 +302 -16
- data/CLAUDE.md +29 -0
- data/CONTRIBUTING.md +138 -20
- data/Gemfile.lock +83 -89
- data/README.md +343 -105
- data/Rakefile +39 -4
- data/TODO.md +50 -0
- data/TODO_v9.md +87 -0
- data/bin/export-bundler-config +11 -0
- data/conductor-setup.sh +70 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/common-upgrades.md +615 -0
- data/docs/css-modules-export-mode.md +512 -0
- data/docs/deployment.md +62 -9
- data/docs/optional-peer-dependencies.md +198 -0
- data/docs/peer-dependencies.md +60 -0
- data/docs/react.md +6 -14
- data/docs/releasing.md +197 -0
- data/docs/rspack.md +190 -0
- data/docs/rspack_migration_guide.md +305 -0
- data/docs/subresource_integrity.md +54 -0
- data/docs/transpiler-migration.md +209 -0
- data/docs/transpiler-performance.md +179 -0
- data/docs/troubleshooting.md +157 -22
- data/docs/typescript-migration.md +379 -0
- data/docs/typescript.md +99 -0
- data/docs/using_esbuild_loader.md +3 -3
- data/docs/using_swc_loader.md +112 -10
- data/docs/v6_upgrade.md +10 -0
- data/docs/v8_upgrade.md +3 -5
- data/docs/v9_upgrade.md +458 -0
- data/gemfiles/Gemfile-rails.6.0.x +2 -1
- data/gemfiles/Gemfile-rails.6.1.x +1 -1
- data/gemfiles/Gemfile-rails.7.0.x +2 -2
- data/gemfiles/Gemfile-rails.7.1.x +1 -2
- data/gemfiles/Gemfile-rails.7.2.x +11 -0
- data/gemfiles/Gemfile-rails.8.0.x +11 -0
- data/lib/install/bin/export-bundler-config +11 -0
- data/lib/install/bin/shakapacker +4 -6
- data/lib/install/bin/shakapacker-dev-server +1 -1
- 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 +25 -5
- 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/bundler_switcher.rb +329 -0
- data/lib/shakapacker/compiler.rb +2 -1
- data/lib/shakapacker/compiler_strategy.rb +2 -2
- data/lib/shakapacker/configuration.rb +173 -2
- data/lib/shakapacker/dev_server_runner.rb +29 -8
- data/lib/shakapacker/digest_strategy.rb +2 -1
- data/lib/shakapacker/doctor.rb +905 -0
- data/lib/shakapacker/helper.rb +64 -16
- data/lib/shakapacker/manifest.rb +10 -3
- data/lib/shakapacker/mtime_strategy.rb +1 -1
- data/lib/shakapacker/railtie.rb +4 -4
- data/lib/shakapacker/rspack_runner.rb +19 -0
- data/lib/shakapacker/runner.rb +159 -10
- data/lib/shakapacker/swc_migrator.rb +384 -0
- data/lib/shakapacker/utils/manager.rb +15 -2
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +2 -2
- data/lib/shakapacker/webpack_runner.rb +6 -43
- data/lib/shakapacker.rb +22 -11
- data/lib/tasks/shakapacker/doctor.rake +8 -0
- data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
- data/lib/tasks/shakapacker/install.rake +12 -2
- data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
- data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
- data/lib/tasks/shakapacker.rake +2 -0
- data/package/.npmignore +4 -0
- data/package/babel/preset.ts +56 -0
- data/package/config.ts +175 -0
- data/package/configExporter/cli.ts +683 -0
- data/package/configExporter/configDocs.ts +102 -0
- data/package/configExporter/fileWriter.ts +92 -0
- data/package/configExporter/index.ts +5 -0
- data/package/configExporter/types.ts +36 -0
- data/package/configExporter/yamlSerializer.ts +266 -0
- data/package/{dev_server.js → dev_server.ts} +8 -5
- data/package/env.ts +92 -0
- data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
- data/package/environments/{base.js → base.ts} +56 -60
- 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 +98 -0
- data/package/esbuild/index.ts +42 -0
- data/package/index.d.ts +3 -60
- data/package/index.ts +55 -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/webpack.ts +16 -0
- data/package/swc/index.ts +56 -0
- data/package/types/README.md +88 -0
- data/package/types/index.ts +61 -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-lock.json +13047 -0
- data/package.json +154 -18
- data/scripts/remove-use-strict.js +45 -0
- data/scripts/type-check-no-emit.js +27 -0
- data/test/helpers.js +1 -1
- data/test/package/config.test.js +43 -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 +4165 -2706
- metadata +129 -41
- data/package/babel/preset.js +0 -37
- data/package/config.js +0 -54
- data/package/env.js +0 -48
- 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/index.js +0 -20
- 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 -58
- 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,28 @@
|
|
|
1
|
+
// @ts-ignore: webpack is an optional peer dependency (using type-only import)
|
|
2
|
+
import type { LoaderDefinitionFunction } from 'webpack'
|
|
3
|
+
|
|
4
|
+
export interface ShakapackerLoaderOptions {
|
|
5
|
+
[key: string]: any
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ShakapackerLoader {
|
|
9
|
+
loader: string
|
|
10
|
+
options?: ShakapackerLoaderOptions
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type LoaderResolver = (name: string) => string
|
|
14
|
+
|
|
15
|
+
export interface LoaderConfig {
|
|
16
|
+
test: RegExp | ((value: string) => boolean)
|
|
17
|
+
use: Array<string | ShakapackerLoader | LoaderDefinitionFunction>
|
|
18
|
+
exclude?: RegExp | string | Array<string>
|
|
19
|
+
include?: RegExp | string | Array<string>
|
|
20
|
+
type?: string
|
|
21
|
+
generator?: {
|
|
22
|
+
filename?: string
|
|
23
|
+
publicPath?: string
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function resolveLoader(name: string): string
|
|
28
|
+
export function createLoader(config: LoaderConfig): LoaderConfig
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { requireOrError } = require("../utils/requireOrError")
|
|
2
|
+
const { error: logError } = require("../utils/debug")
|
|
3
|
+
|
|
4
|
+
const rspack = requireOrError("@rspack/core")
|
|
5
|
+
|
|
6
|
+
interface OptimizationConfig {
|
|
7
|
+
minimize: boolean
|
|
8
|
+
minimizer?: unknown[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const getOptimization = (): OptimizationConfig => {
|
|
12
|
+
// Use Rspack's built-in minification instead of terser-webpack-plugin
|
|
13
|
+
const result: OptimizationConfig = { minimize: true }
|
|
14
|
+
try {
|
|
15
|
+
result.minimizer = [
|
|
16
|
+
new rspack.SwcJsMinimizerRspackPlugin(),
|
|
17
|
+
new rspack.LightningCssMinimizerRspackPlugin()
|
|
18
|
+
]
|
|
19
|
+
} catch (error: unknown) {
|
|
20
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
21
|
+
const errorStack = error instanceof Error ? error.stack : ''
|
|
22
|
+
// Log full error with stack trace
|
|
23
|
+
logError(
|
|
24
|
+
`Failed to configure Rspack minimizers: ${errorMessage}\n${errorStack}`
|
|
25
|
+
)
|
|
26
|
+
// Re-throw the error to properly propagate it
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Could not configure Rspack minimizers: ${errorMessage}. Please check that @rspack/core is properly installed.`
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
return result
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export = {
|
|
35
|
+
getOptimization
|
|
36
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { requireOrError } = require("../utils/requireOrError")
|
|
2
|
+
|
|
3
|
+
const TerserPlugin = requireOrError("terser-webpack-plugin")
|
|
4
|
+
const { moduleExists } = require("../utils/helpers")
|
|
5
|
+
|
|
6
|
+
const tryCssMinimizer = (): unknown | null => {
|
|
7
|
+
if (
|
|
8
|
+
moduleExists("css-loader") &&
|
|
9
|
+
moduleExists("css-minimizer-webpack-plugin")
|
|
10
|
+
) {
|
|
11
|
+
const CssMinimizerPlugin = requireOrError("css-minimizer-webpack-plugin")
|
|
12
|
+
return new CssMinimizerPlugin()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface OptimizationConfig {
|
|
19
|
+
minimizer: unknown[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getOptimization = (): OptimizationConfig => {
|
|
23
|
+
return {
|
|
24
|
+
minimizer: [
|
|
25
|
+
tryCssMinimizer(),
|
|
26
|
+
new TerserPlugin({
|
|
27
|
+
// SHAKAPACKER_PARALLEL env var: number of parallel workers, or true for auto (os.cpus().length - 1)
|
|
28
|
+
// If not set or invalid, defaults to true (automatic parallelization)
|
|
29
|
+
parallel: process.env.SHAKAPACKER_PARALLEL
|
|
30
|
+
? Number.parseInt(process.env.SHAKAPACKER_PARALLEL, 10) || true
|
|
31
|
+
: true,
|
|
32
|
+
terserOptions: {
|
|
33
|
+
parse: {
|
|
34
|
+
// Let terser parse ecma 8 code but always output
|
|
35
|
+
// ES5 compliant code for older browsers
|
|
36
|
+
ecma: 8
|
|
37
|
+
},
|
|
38
|
+
compress: {
|
|
39
|
+
ecma: 5,
|
|
40
|
+
warnings: false,
|
|
41
|
+
comparisons: false
|
|
42
|
+
},
|
|
43
|
+
mangle: { safari10: true },
|
|
44
|
+
output: {
|
|
45
|
+
ecma: 5,
|
|
46
|
+
comments: false,
|
|
47
|
+
ascii_only: true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
].filter(Boolean)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export = {
|
|
56
|
+
getOptimization
|
|
57
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const { requireOrError } = require("../utils/requireOrError")
|
|
2
|
+
|
|
3
|
+
const { RspackManifestPlugin } = requireOrError("rspack-manifest-plugin")
|
|
4
|
+
const rspack = requireOrError("@rspack/core")
|
|
5
|
+
const config = require("../config")
|
|
6
|
+
const { isProduction } = require("../env")
|
|
7
|
+
const { moduleExists } = require("../utils/helpers")
|
|
8
|
+
|
|
9
|
+
interface ManifestFile {
|
|
10
|
+
name: string
|
|
11
|
+
path: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface EntrypointAssets {
|
|
15
|
+
js: string[]
|
|
16
|
+
css: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface Manifest {
|
|
20
|
+
entrypoints?: Record<string, { assets: EntrypointAssets }>
|
|
21
|
+
[key: string]: string | { assets: EntrypointAssets } | Record<string, { assets: EntrypointAssets }> | undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const getPlugins = (): unknown[] => {
|
|
25
|
+
const plugins = [
|
|
26
|
+
new rspack.EnvironmentPlugin(process.env),
|
|
27
|
+
new RspackManifestPlugin({
|
|
28
|
+
fileName: config.manifestPath.split("/").pop(), // Get just the filename
|
|
29
|
+
publicPath: config.publicPathWithoutCDN,
|
|
30
|
+
writeToFileEmit: true,
|
|
31
|
+
// rspack-manifest-plugin uses different option names than webpack-assets-manifest
|
|
32
|
+
generate: (seed: Manifest | null, files: ManifestFile[], entrypoints: Record<string, string[]>) => {
|
|
33
|
+
const manifest: Manifest = seed || {}
|
|
34
|
+
|
|
35
|
+
// Add files mapping first
|
|
36
|
+
files.forEach((file) => {
|
|
37
|
+
manifest[file.name] = file.path
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// Add entrypoints information compatible with Shakapacker expectations
|
|
41
|
+
const entrypointsManifest: Record<string, { assets: EntrypointAssets }> = {}
|
|
42
|
+
Object.entries(entrypoints).forEach(
|
|
43
|
+
([entrypointName, entrypointFiles]) => {
|
|
44
|
+
const jsFiles = entrypointFiles
|
|
45
|
+
.filter(
|
|
46
|
+
(file) => file.endsWith(".js") && !file.includes(".hot-update.")
|
|
47
|
+
)
|
|
48
|
+
.map((file) => config.publicPathWithoutCDN + file)
|
|
49
|
+
const cssFiles = entrypointFiles
|
|
50
|
+
.filter(
|
|
51
|
+
(file) =>
|
|
52
|
+
file.endsWith(".css") && !file.includes(".hot-update.")
|
|
53
|
+
)
|
|
54
|
+
.map((file) => config.publicPathWithoutCDN + file)
|
|
55
|
+
|
|
56
|
+
entrypointsManifest[entrypointName] = {
|
|
57
|
+
assets: {
|
|
58
|
+
js: jsFiles,
|
|
59
|
+
css: cssFiles
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
manifest.entrypoints = entrypointsManifest
|
|
65
|
+
|
|
66
|
+
return manifest
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
if (moduleExists("css-loader")) {
|
|
72
|
+
const hash = isProduction || config.useContentHash ? "-[contenthash:8]" : ""
|
|
73
|
+
// Use Rspack's built-in CSS extraction
|
|
74
|
+
const { CssExtractRspackPlugin } = rspack
|
|
75
|
+
plugins.push(
|
|
76
|
+
new CssExtractRspackPlugin({
|
|
77
|
+
filename: `css/[name]${hash}.css`,
|
|
78
|
+
chunkFilename: `css/[id]${hash}.css`,
|
|
79
|
+
// For projects where css ordering has been mitigated through consistent use of scoping or naming conventions,
|
|
80
|
+
// the css order warnings can be disabled by setting the ignoreOrder flag.
|
|
81
|
+
ignoreOrder: config.css_extract_ignore_order_warnings,
|
|
82
|
+
// Force writing CSS files to disk in development for Rails compatibility
|
|
83
|
+
emit: true
|
|
84
|
+
})
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Use Rspack's built-in SubresourceIntegrityPlugin
|
|
89
|
+
if (config.integrity.enabled) {
|
|
90
|
+
plugins.push(
|
|
91
|
+
new rspack.SubresourceIntegrityPlugin({
|
|
92
|
+
hashFuncNames: config.integrity.hash_functions,
|
|
93
|
+
enabled: isProduction
|
|
94
|
+
})
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return plugins
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export = {
|
|
102
|
+
getPlugins
|
|
103
|
+
}
|
|
@@ -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()
|