diff --git a/crates/rspack_core/src/context_module_factory.rs b/crates/rspack_core/src/context_module_factory.rs index 7be0092054ea..4f34474601b3 100644 --- a/crates/rspack_core/src/context_module_factory.rs +++ b/crates/rspack_core/src/context_module_factory.rs @@ -73,6 +73,7 @@ impl ContextModuleFactory { let resolve_args = ResolveArgs { context: data.context.clone(), importer: None, + issuer: data.issuer.as_ref().map(|i| &**i), specifier, dependency_type: dependency.dependency_type(), dependency_category: dependency.category(), diff --git a/crates/rspack_core/src/diagnostics.rs b/crates/rspack_core/src/diagnostics.rs index 3f2c511189fc..e4bfe49537b4 100644 --- a/crates/rspack_core/src/diagnostics.rs +++ b/crates/rspack_core/src/diagnostics.rs @@ -149,6 +149,7 @@ impl miette::Diagnostic for WithHelp { } fn help<'a>(&'a self) -> Option> { + // Use overwritten help message instead. self.1.as_ref().map(Box::new).map(|h| h as Box) } diff --git a/crates/rspack_core/src/normal_module_factory.rs b/crates/rspack_core/src/normal_module_factory.rs index 32383c8a110c..71fc51350108 100644 --- a/crates/rspack_core/src/normal_module_factory.rs +++ b/crates/rspack_core/src/normal_module_factory.rs @@ -278,6 +278,7 @@ impl NormalModuleFactory { let resolve_args = ResolveArgs { importer, + issuer: data.issuer.as_ref().map(|i| &**i), context: if context_scheme != Scheme::None { self.options.context.clone() } else { @@ -337,58 +338,6 @@ impl NormalModuleFactory { Err(err) => { data.add_file_dependencies(file_dependencies); data.add_missing_dependencies(missing_dependencies); - // let mut file_dependencies = Default::default(); - // let mut missing_dependencies = Default::default(); - // let mut from_cache_result = from_cache; - // if !data - // .resolve_options - // .as_ref() - // .and_then(|x| x.fully_specified) - // .unwrap_or(false) - // { - // let new_args = ResolveArgs { - // importer, - // context: if context_scheme != Scheme::None { - // self.options.context.clone() - // } else { - // data.context.clone() - // }, - // specifier: request_without_match_resource, - // dependency_type: dependency.dependency_type(), - // dependency_category: dependency.category(), - // resolve_options: data.resolve_options.take(), - // span: dependency.span(), - // resolve_to_context: false, - // optional, - // missing_dependencies: &mut missing_dependencies, - // file_dependencies: &mut file_dependencies, - // }; - // let (resource_data, from_cache) = match self - // .cache - // .resolve_module_occasion - // .use_cache(new_args, |args| resolve(args, plugin_driver)) - // .await - // { - // Ok(result) => result, - // Err(err) => (Err(err), false), - // }; - // from_cache_result = from_cache; - // if let Ok(ResolveResult::Resource(resource)) = resource_data { - // // TODO: Here windows resolver will return normalized path. - // // eg. D:\a\rspack\rspack\packages\rspack\tests\fixtures\errors\resolve-fail-esm\answer.js - // if let Some(_extension) = resource.path.extension() { - // // let resource = format!( - // // "{request_without_match_resource}.{}", - // // extension.to_string_lossy() - // // ); - // // diagnostics[0].add_notes(vec![format!("Did you mean '{resource}'? - // // BREAKING CHANGE: The request '{request_without_match_resource}' failed to resolve only because it was resolved as fully specified - // // (probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\"type\": \"module\"'). - // // The extension in the request is mandatory for it to be fully specified. - // // Add the extension to the request.")]); - // } - // } - // } return Err(err); } } diff --git a/crates/rspack_core/src/options/resolve/mod.rs b/crates/rspack_core/src/options/resolve/mod.rs index d20c1fdbfdc0..812d86ce922d 100644 --- a/crates/rspack_core/src/options/resolve/mod.rs +++ b/crates/rspack_core/src/options/resolve/mod.rs @@ -130,6 +130,28 @@ impl Resolve { pub fn merge(self, value: Self) -> Self { clever_merge::merge_resolve(self, value) } + + pub fn fully_specified(&self, cat: Option<&DependencyCategory>) -> Option { + cat + .and_then(|cat| { + self + .by_dependency + .as_ref() + .and_then(|by_dep| by_dep.get(cat).and_then(|d| d.fully_specified)) + }) + .or(self.fully_specified) + } + + pub fn prefer_relative(&self, cat: Option<&DependencyCategory>) -> Option { + cat + .and_then(|cat| { + self + .by_dependency + .as_ref() + .and_then(|by_dep| by_dep.get(cat).and_then(|d| d.prefer_relative)) + }) + .or(self.prefer_relative) + } } type DependencyCategoryStr = Cow<'static, str>; diff --git a/crates/rspack_core/src/plugin/args.rs b/crates/rspack_core/src/plugin/args.rs index 04bc7492ecd0..6e87982bdb54 100644 --- a/crates/rspack_core/src/plugin/args.rs +++ b/crates/rspack_core/src/plugin/args.rs @@ -101,6 +101,7 @@ pub struct NormalModuleAfterResolveArgs<'a> { #[derive(Debug)] pub struct ResolveArgs<'a> { pub importer: Option<&'a ModuleIdentifier>, + pub issuer: Option<&'a str>, pub context: Context, pub specifier: &'a str, pub dependency_type: &'a DependencyType, diff --git a/crates/rspack_core/src/resolver/mod.rs b/crates/rspack_core/src/resolver/mod.rs index 674b57aaf4d2..e42994456d12 100644 --- a/crates/rspack_core/src/resolver/mod.rs +++ b/crates/rspack_core/src/resolver/mod.rs @@ -3,14 +3,26 @@ mod resolver_impl; use std::{fmt, path::PathBuf}; -use rspack_error::Error; +use once_cell::sync::Lazy; +use regex::Regex; +use rspack_error::{DiagnosticExt, Error}; use rspack_loader_runner::DescriptionData; +use sugar_path::{AsPath, SugarPath}; pub use self::factory::{ResolveOptionsWithDependencyType, ResolverFactory}; pub use self::resolver_impl::{ResolveInnerOptions, Resolver}; use crate::diagnostics::WithHelp; use crate::{ResolveArgs, SharedPluginDriver}; +static RELATIVE_PATH_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^\.\.?\/").expect("should init regex")); + +static PARENT_PATH_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^\.\.[\/]").expect("should init regex")); + +static CURRENT_DIR_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^(\.[\/])").expect("should init regex")); + /// A successful path resolution or an ignored path. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ResolveResult { @@ -56,13 +68,113 @@ impl Resource { } } +pub fn resolve_for_error_hints( + args: ResolveArgs<'_>, + plugin_driver: &SharedPluginDriver, +) -> Option { + let dep = ResolveOptionsWithDependencyType { + resolve_options: args.resolve_options.clone(), + resolve_to_context: args.resolve_to_context, + dependency_category: *args.dependency_category, + }; + + let base_dir = args.context.clone(); + let base_dir = base_dir.as_ref(); + + let fully_specified = dep + .resolve_options + .as_ref() + .and_then(|o| o.fully_specified(Some(&args.dependency_category))) + .unwrap_or_default(); + + let prefer_relative = dep + .resolve_options + .as_ref() + .and_then(|o| o.prefer_relative(Some(&args.dependency_category))) + .unwrap_or_default(); + + // Try to resolve without fully specified + if fully_specified { + let mut dep = dep.clone(); + dep.resolve_options = dep.resolve_options.map(|mut options| { + options.fully_specified = Some(false); + options + }); + let resolver = plugin_driver.resolver_factory.get(dep); + match resolver.resolve(base_dir, args.specifier) { + Ok(ResolveResult::Resource(resource)) => { + let relative_path = resource.path.relative(args.context.as_path()); + let suggestion = if let Some((_, [prefix])) = CURRENT_DIR_REGEX + .captures_iter(args.specifier) + .next() + .map(|c| c.extract()) + { + // If the specifier is a relative path pointing to the current directory, + // we can suggest the path relative to the current directory. + format!("{}{}", prefix, relative_path.to_string_lossy()) + } else if PARENT_PATH_REGEX.is_match(args.specifier) { + // If the specifier is a relative path to which the parent directory is, + // then we return the relative path directly. + relative_path.to_string_lossy().to_string() + } else { + // If the specifier is a package name like or some arbitrary alias, + // then we return the full path. + resource.path.to_string_lossy().to_string() + }; + return Some(format!("Did you mean '{}'? + +The request '{}' failed to resolve only because it was resolved as fully specified, +probably because the origin '{}' is strict EcmaScript Module, +e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\"type\": \"module\"'. + +The extension in the request is mandatory for it to be fully specified. +Add the extension to the request.", suggestion, args.specifier, args.issuer.unwrap_or_default())); + } + Err(_) => return None, + _ => {} + } + } + + // Try to resolve with relative path if request is not relative + if !RELATIVE_PATH_REGEX.is_match(args.specifier) && !prefer_relative { + let dep = dep.clone(); + let module_directories = dep + .resolve_options + .as_ref() + .map(|r| &**r) + .or(Some(&plugin_driver.options.resolve)) + .and_then(|o| o.modules.as_ref().map(|m| m.join(", "))) + .expect("module directories should exist"); + let resolver = plugin_driver.resolver_factory.get(dep); + let request = format!("./{}", args.specifier); + match resolver.resolve(base_dir, &request) { + Ok(ResolveResult::Resource(_)) => { + return Some(format!( + "Did you mean './{}'? + +Requests that should resolve in the current directory need to start with './'. +Requests that start with a name are treated as module requests and resolve within module directories ({module_directories}). + +If changing the source code is not an option, there is also a resolve options called 'preferRelative' +which tries to resolve these kind of requests in the current directory too.", + args.specifier + )); + } + Err(_) => return None, + _ => {} + } + } + + None +} + /// Main entry point for module resolution. pub async fn resolve( - mut args: ResolveArgs<'_>, + args: ResolveArgs<'_>, plugin_driver: &SharedPluginDriver, ) -> Result { let dep = ResolveOptionsWithDependencyType { - resolve_options: args.resolve_options.take(), + resolve_options: args.resolve_options.clone(), resolve_to_context: args.resolve_to_context, dependency_category: *args.dependency_category, }; @@ -72,7 +184,7 @@ pub async fn resolve( let mut context = Default::default(); let resolver = plugin_driver.resolver_factory.get(dep); - let result = resolver + let mut result = resolver .resolve_with_context(base_dir, args.specifier, &mut context) .map_err(|error| error.into_resolve_error(&args)); @@ -81,5 +193,11 @@ pub async fn resolve( .missing_dependencies .extend(context.missing_dependencies); + if result.is_err() + && let Some(hint) = resolve_for_error_hints(args, plugin_driver) + { + result = result.map_err(|err| WithHelp::from(err).with_help(hint).boxed()) + }; + result.map_err(|err| Error::new_boxed(err)) } diff --git a/crates/rspack_core/src/resolver/resolver_impl.rs b/crates/rspack_core/src/resolver/resolver_impl.rs index 533c6cde462e..cb894b7f4d44 100644 --- a/crates/rspack_core/src/resolver/resolver_impl.rs +++ b/crates/rspack_core/src/resolver/resolver_impl.rs @@ -6,7 +6,7 @@ use std::{ use rspack_error::{ miette::{diagnostic, Diagnostic}, - DiagnosticError, DiagnosticExt, Severity, TraceableError, + DiagnosticExt, Severity, TraceableError, }; use rspack_loader_runner::DescriptionData; use rustc_hash::FxHashSet as HashSet; @@ -277,12 +277,15 @@ fn to_oxc_resolver_options( } } -fn map_oxc_resolver_error(error: oxc_resolver::ResolveError, args: &ResolveArgs<'_>) -> Error { +fn map_oxc_resolver_error( + error: oxc_resolver::ResolveError, + args: &ResolveArgs<'_>, +) -> Box { match error { - oxc_resolver::ResolveError::IOError(error) => DiagnosticError::from(error.boxed()).into(), + oxc_resolver::ResolveError::IOError(error) => diagnostic!("{}", error).boxed(), oxc_resolver::ResolveError::Recursion => map_resolver_error(true, args), oxc_resolver::ResolveError::NotFound(_) => map_resolver_error(false, args), - _ => error!("{}", error), + _ => diagnostic!("{}", error).boxed(), } } diff --git a/examples/basic/src/index.js b/examples/basic/src/index.js index c52be0607891..ac0087506076 100644 --- a/examples/basic/src/index.js +++ b/examples/basic/src/index.js @@ -1,4 +1,4 @@ -import { answer } from "./answerrr"; +import { answer } from "./answer"; function render() { document.getElementById( "root" diff --git a/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts b/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts index 1c4be026fddc..d4230789ec03 100644 --- a/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts +++ b/packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts @@ -607,9 +607,7 @@ const SIMPLE_PRINTERS: Record< // "error.details": (details, { formatError }) => formatError(details), // "error.stack": stack => stack, // "error.moduleTrace": moduleTrace => undefined, - // "error.separator!": () => "\n", - // Error was already formatted on the native. - // error: error => error, + "error.separator!": () => "\n", "loggingEntry(error).loggingEntry.message": (message, { red }) => mapLines(message, x => ` ${red(x)}`), diff --git a/packages/rspack/tests/Errors.test.ts b/packages/rspack/tests/Errors.test.ts index 7b73930a4610..c7860d64d255 100644 --- a/packages/rspack/tests/Errors.test.ts +++ b/packages/rspack/tests/Errors.test.ts @@ -146,8 +146,8 @@ it("should emit warnings for resolve failure in esm", async () => { Object { "errors": Array [ Object { - "formatted": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n", - "message": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n", + "formatted": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n help: Did you mean './answer.js'?\\n \\n The request './answer' failed to resolve only because it was resolved as fully specified,\\n probably because the origin '/tests/fixtures/errors/resolve-fail-esm/index.js' is strict EcmaScript Module,\\n e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\\"type\\": \\"module\\"'.\\n \\n The extension in the request is mandatory for it to be fully specified.\\n Add the extension to the request.\\n", + "message": " × Resolve error: Can't resolve './answer' in '/tests/fixtures/errors/resolve-fail-esm'\\n ╭────\\n 1 │ import { answer } from './answer';\\n · ──────────\\n ╰────\\n help: Did you mean './answer.js'?\\n \\n The request './answer' failed to resolve only because it was resolved as fully specified,\\n probably because the origin '/tests/fixtures/errors/resolve-fail-esm/index.js' is strict EcmaScript Module,\\n e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '\\"type\\": \\"module\\"'.\\n \\n The extension in the request is mandatory for it to be fully specified.\\n Add the extension to the request.\\n", "moduleId": "./resolve-fail-esm/index.js", "moduleIdentifier": "javascript/esm|/tests/fixtures/errors/resolve-fail-esm/index.js", "moduleName": "./resolve-fail-esm/index.js", diff --git a/packages/rspack/tests/Stats.test.ts b/packages/rspack/tests/Stats.test.ts index 35bccd1429e3..b6eca134cc42 100644 --- a/packages/rspack/tests/Stats.test.ts +++ b/packages/rspack/tests/Stats.test.ts @@ -66,7 +66,8 @@ describe("Stats", () => { ./fixtures/c.js ./fixtures/abc.js - ERROR in ./fixtures/b.js ModuleParseError + ERROR in ./fixtures/b.js + ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Return statement is not allowed here diff --git a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap index 6386d37a7e9e..dbea104fd4e6 100644 --- a/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap +++ b/packages/rspack/tests/__snapshots__/StatsTestCases.test.ts.snap @@ -829,7 +829,7 @@ exports[`StatsTestCases should print correct stats for hot+production 1`] = ` "hotModuleReplacement": false, }, "name": "bundle.js", - "size": 9108, + "size": 9038, "type": "asset", }, ], @@ -894,10 +894,10 @@ exports[`StatsTestCases should print correct stats for hot+production 1`] = ` "assets": [ { "name": "bundle.js", - "size": 9108, + "size": 9038, }, ], - "assetsSize": 9108, + "assetsSize": 9038, "chunks": [ "909", ], @@ -907,7 +907,7 @@ exports[`StatsTestCases should print correct stats for hot+production 1`] = ` "errors": [], "errorsCount": 0, "filteredModules": undefined, - "hash": "5f9f75789352d7c6b706", + "hash": "d938674585ad9aa214d9", "logging": {}, "modules": [ { @@ -1065,10 +1065,10 @@ exports[`StatsTestCases should print correct stats for hot+production 1`] = ` "assets": [ { "name": "bundle.js", - "size": 9108, + "size": 9038, }, ], - "assetsSize": 9108, + "assetsSize": 9038, "chunks": [ "909", ], @@ -1084,8 +1084,8 @@ exports[`StatsTestCases should print correct stats for hot+production 1`] = ` exports[`StatsTestCases should print correct stats for hot+production 2`] = ` "PublicPath: (none) -asset bundle.js 8.89 KiB {909} [emitted] (name: main) -Entrypoint main 8.89 KiB = bundle.js +asset bundle.js 8.83 KiB {909} [emitted] (name: main) +Entrypoint main 8.83 KiB = bundle.js chunk {909} bundle.js (main) [entry] ./index.js [10] {909} entry ./index.js @@ -1098,7 +1098,7 @@ webpack/runtime/hot_module_replacement {909} webpack/runtime/get_chunk_update_filename {909} webpack/runtime/get_main_filename/update manifest {909} -Rspack compiled successfully (5f9f75789352d7c6b706)" +Rspack compiled successfully (d938674585ad9aa214d9)" `; exports[`StatsTestCases should print correct stats for identifier-let-strict-mode 1`] = ` @@ -1171,7 +1171,8 @@ exports[`StatsTestCases should print correct stats for identifier-let-strict-mod `; exports[`StatsTestCases should print correct stats for identifier-let-strict-mode 2`] = ` -"ERROR in ./index.js ModuleParseError +"ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: \`let\` cannot be used as an identifier in strict mode @@ -1183,7 +1184,8 @@ exports[`StatsTestCases should print correct stats for identifier-let-strict-mod help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: \`let\` cannot be used as an identifier in strict mode @@ -4212,7 +4214,8 @@ exports[`StatsTestCases should print correct stats for loader-builtin-swc-plugin `; exports[`StatsTestCases should print correct stats for loader-builtin-swc-plugin-warn 2`] = ` -"WARNING in ./index.js builtin:swc-loader +"WARNING in ./index.js +builtin:swc-loader ⚠ Experimental plugins are not currently supported. @@ -4389,7 +4392,8 @@ exports[`StatsTestCases should print correct stats for normal-errors 1`] = ` `; exports[`StatsTestCases should print correct stats for normal-errors 2`] = ` -"ERROR in ./index.js × Resolve error: Can't resolve 'not-exist' in '/tests/statsCases/normal-errors' +"ERROR in ./index.js + × Resolve error: Can't resolve 'not-exist' in '/tests/statsCases/normal-errors' ╭──── 1 │ import "not-exist"; · ─────────── @@ -5013,7 +5017,8 @@ exports[`StatsTestCases should print correct stats for parse-error 1`] = ` `; exports[`StatsTestCases should print correct stats for parse-error 2`] = ` -"ERROR in ./b.js ModuleParseError +"ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ';', '}' or @@ -5065,7 +5070,8 @@ exports[`StatsTestCases should print correct stats for parse-error-builtin-swc-l `; exports[`StatsTestCases should print correct stats for parse-error-builtin-swc-loader 2`] = ` -"ERROR in ./index.ts × x Expected '{', got 'error' +"ERROR in ./index.ts + × x Expected '{', got 'error' │ ,-[/tests/statsCases/parse-error-builtin-swc-loader/index.ts:1:1] │ 1 | export error; │ : ^^^^^ @@ -5341,7 +5347,8 @@ chunk {909} bundle.js (main) [entry] webpack/runtime/make_namespace_object {909} -ERROR in ./index.js × Resolve error: Can't resolve 'cycle-alias/a' in '/tests/statsCases/resolve-overflow' +ERROR in ./index.js + × Resolve error: Can't resolve 'cycle-alias/a' in '/tests/statsCases/resolve-overflow' ╭─[1:1] 1 │ import { a } from "cycle-alias/a"; · ─────────────── @@ -5545,7 +5552,8 @@ chunk {909} bundle.js (main) [entry] webpack/runtime/make_namespace_object {909} -ERROR in ./index.js × Invalid "exports" target "../../index.js" defined for '.' in the package config /tests/statsCases/resolve-unexpected-exports-in-pkg/node_modules/pkg-a/package.json +ERROR in ./index.js + × Invalid "exports" target "../../index.js" defined for '.' in the package config /tests/statsCases/resolve-unexpected-exports-in-pkg/node_modules/pkg-a/package.json Rspack compiled with 1 error (d522bd63336c0fb69e32)" `; @@ -6463,7 +6471,8 @@ exports[`StatsTestCases should print correct stats for try-require--module 1`] = `; exports[`StatsTestCases should print correct stats for try-require--module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require--module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require--module' ╭─[1:1] 1 │ try { 2 │ require('./missing-module'); @@ -6507,7 +6516,8 @@ exports[`StatsTestCases should print correct stats for try-require-resolve-modul `; exports[`StatsTestCases should print correct stats for try-require-resolve-module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-module' ╭─[1:1] 1 │ try { 2 │ require.resolve('./missing-module'); @@ -6551,7 +6561,8 @@ exports[`StatsTestCases should print correct stats for try-require-resolve-weak- `; exports[`StatsTestCases should print correct stats for try-require-resolve-weak-module 2`] = ` -"WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-weak-module' +"WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/statsCases/try-require-resolve-weak-module' ╭─[1:1] 1 │ try { 2 │ require.resolveWeak('./missing-module'); diff --git a/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err index 6462796cf7db..ce8f38d2fe22 100644 --- a/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/asset-module-build-failed/stats.err @@ -1,4 +1,5 @@ -ERROR in ./logo.svg NapiError +ERROR in ./logo.svg +NapiError × Napi Error: Error: Failed to load │ at Object..module.exports (/tests/diagnostics/factorize/asset-module-build-failed/my-loader.js:2:8) diff --git a/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err b/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err index 5f89a3d05aef..4a8975875a95 100644 --- a/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/cannot-resolve-with-loader/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve-with-loader' +ERROR in ./index.js + × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve-with-loader' ╭─[1:1] 1 │ // THIS SHOULD BE INCLUDED IN THE DIAGNOSTIC 2 │ require("./a"); diff --git a/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err b/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err index da84aaaf5e4c..8db176f68862 100644 --- a/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/cannot-resolve/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve' +ERROR in ./index.js + × Resolve error: Can't resolve './a' in '/tests/diagnostics/factorize/cannot-resolve' ╭──── 1 │ import "./a"; · ───── diff --git a/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err b/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err index 3d809720fcd1..cd243f78629f 100644 --- a/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/css-module-request-prefix/stats.err @@ -1,4 +1,5 @@ -WARNING in ./index.css ModuleParseWarning +WARNING in ./index.css +ModuleParseWarning ⚠ Module parse warning: ╰─▶ ⚠ css: Deprecated '~' diff --git a/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err b/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err index a0d90f344b09..a7a81a509c7f 100644 --- a/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/dynamic-import-non-exist-module/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js × Resolve error: Can't resolve './non-exist' in '/tests/diagnostics/factorize/dynamic-import-non-exist-module' +ERROR in ./index.js + × Resolve error: Can't resolve './non-exist' in '/tests/diagnostics/factorize/dynamic-import-non-exist-module' ╭─[2:1] 2 │ let errored = false; 3 │ try { diff --git a/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err b/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err index 21ccc68da9e7..e6f4381923ff 100644 --- a/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/empty-dependency/stats.err @@ -1,11 +1,13 @@ -ERROR in ./index.js × Empty dependency: Expected a non-empty request +ERROR in ./index.js + × Empty dependency: Expected a non-empty request ╭─[1:1] 1 │ require(""); · ─────────── 2 │ import ""; ╰──── -ERROR in ./index.js × Empty dependency: Expected a non-empty request +ERROR in ./index.js + × Empty dependency: Expected a non-empty request ╭─[1:1] 1 │ require(""); 2 │ import ""; diff --git a/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err b/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err new file mode 100644 index 000000000000..923a85a4fad6 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/experiments-disable-transform-parse-error/stats.err @@ -0,0 +1 @@ +ERROR in × Resolve error: Can't resolve './' in '/tests/diagnostics/factorize/experiments-disable-transform-parse-error' diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/foo.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/foo.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js new file mode 100644 index 000000000000..5003c98cd2f7 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js @@ -0,0 +1 @@ +import "./foo" diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err new file mode 100644 index 000000000000..4d4570c56d6a --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/stats.err @@ -0,0 +1,14 @@ +ERROR in ./index.js + × Resolve error: Can't resolve './foo' in '/tests/diagnostics/factorize/fully-specified-resolve-suggestions' + ╭──── + 1 │ import "./foo"; + · ─────── + ╰──── + help: Did you mean './foo.js'? + + The request './foo' failed to resolve only because it was resolved as fully specified, + probably because the origin '/tests/diagnostics/factorize/fully-specified-resolve-suggestions/index.js' is strict EcmaScript Module, + e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"'. + + The extension in the request is mandatory for it to be fully specified. + Add the extension to the request. diff --git a/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js new file mode 100644 index 000000000000..e35d3db6c18b --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/fully-specified-resolve-suggestions/webpack.config.js @@ -0,0 +1,13 @@ +module.exports = { + module: { + rules: [ + { + test: /\.js$/, + resolve: { + fullySpecified: true + }, + type: "javascript/esm" + } + ] + } +} diff --git a/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err index 9ffe2ea480d5..dba96be250cc 100644 --- a/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/json-module-build-failed/stats.err @@ -1,4 +1,5 @@ -ERROR in ./syntax-error.json × Json parsing error: Unexpected character } +ERROR in ./syntax-error.json + × Json parsing error: Unexpected character } ╭─[1:1] 1 │ { 2 │ "a" diff --git a/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err b/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err index 6371e5f42b20..c2c3a5618eab 100644 --- a/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/loader-throw-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./lib.js NapiError +ERROR in ./lib.js +NapiError × Napi Error: Error: Failed to load │ at Object..module.exports (/tests/diagnostics/factorize/loader-throw-error/my-loader.js:2:9) diff --git a/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err b/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err index 4aa3cd587725..f7e0448390fe 100644 --- a/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/mismatched-module-type/stats.err @@ -1,4 +1,5 @@ -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Unterminated regexp literal @@ -12,7 +13,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -26,7 +28,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.js ModuleParseError +ERROR in ./app.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -40,7 +43,8 @@ ERROR in ./app.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Unterminated regexp literal @@ -54,7 +58,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -68,7 +73,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.jsx ModuleParseError +ERROR in ./app.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -82,7 +88,8 @@ ERROR in ./app.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./app.ts ModuleParseError +ERROR in ./app.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ',', got ':' @@ -97,4 +104,5 @@ ERROR in ./app.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js × No parser registered for 'ts' +ERROR in ./index.js + × No parser registered for 'ts' diff --git a/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err b/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err index efffb8fd925a..0d2f3c15b945 100644 Binary files a/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err and b/packages/rspack/tests/diagnostics/factorize/missing-config-build-failed/stats.err differ diff --git a/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err b/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err index f63b248cb149..c320f14bd90a 100644 --- a/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/missing-module/stats.err @@ -1,4 +1,5 @@ -WARNING in ./index.js ⚠ Resolve error: Can't resolve './missing-module' in '/tests/diagnostics/factorize/missing-module' +WARNING in ./index.js + ⚠ Resolve error: Can't resolve './missing-module' in '/tests/diagnostics/factorize/missing-module' ╭─[2:1] 2 │ let errored = false; 3 │ try { diff --git a/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err b/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err index 0a5f12360f25..1d96a7047623 100644 --- a/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/module-parse-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./non-recoverable.js ModuleParseError +ERROR in ./non-recoverable.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ident @@ -10,7 +11,8 @@ ERROR in ./non-recoverable.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./recoverable.js ModuleParseError +ERROR in ./recoverable.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/foo.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/foo.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js new file mode 100644 index 000000000000..46ff4caab269 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/index.js @@ -0,0 +1 @@ +import "foo.js" diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err new file mode 100644 index 000000000000..9295c4ced1cf --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/stats.err @@ -0,0 +1,13 @@ +ERROR in ./index.js + × Resolve error: Can't resolve 'foo.js' in '/tests/diagnostics/factorize/prefer-relative-resolve-suggestions' + ╭──── + 1 │ import "foo.js"; + · ──────── + ╰──── + help: Did you mean './foo.js'? + + Requests that should resolve in the current directory need to start with './'. + Requests that start with a name are treated as module requests and resolve within module directories (node_modules). + + If changing the source code is not an option, there is also a resolve options called 'preferRelative' + which tries to resolve these kind of requests in the current directory too. diff --git a/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js new file mode 100644 index 000000000000..cc432c6ebad7 --- /dev/null +++ b/packages/rspack/tests/diagnostics/factorize/prefer-relative-resolve-suggestions/webpack.config.js @@ -0,0 +1,10 @@ +module.exports = { + module: { + rules: [ + { + test: /\.js$/, + type: "javascript/esm" + } + ] + } +} diff --git a/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err b/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err index fa927685d4de..39d59392a235 100644 --- a/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err +++ b/packages/rspack/tests/diagnostics/factorize/rule-type-fatal-error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./jsx.jsx ModuleParseError +ERROR in ./jsx.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -10,7 +11,8 @@ ERROR in ./jsx.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./jsx.jsx ModuleParseError +ERROR in ./jsx.jsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -22,7 +24,8 @@ ERROR in ./jsx.jsx ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./ts.ts ModuleParseError +ERROR in ./ts.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -34,7 +37,8 @@ ERROR in ./ts.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./ts.ts ModuleParseError +ERROR in ./ts.ts +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: An arrow function is not allowed here @@ -46,7 +50,8 @@ ERROR in ./ts.ts ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./tsx.tsx ModuleParseError +ERROR in ./tsx.tsx +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected '(', got '<' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err index fb40c349b59a..39108f5db66c 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/basic/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected ',', got ':' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err new file mode 100644 index 000000000000..1ef732528ac5 --- /dev/null +++ b/packages/rspack/tests/diagnostics/module-parse-failed/jsx_syntax_error/stats.err @@ -0,0 +1 @@ +ERROR in × Resolve error: Can't resolve './' in '/tests/diagnostics/module-parse-failed/jsx_syntax_error' diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err index 439fe3dd6c0b..d0b74333e36e 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/lack-equal/stats.err @@ -1,4 +1,5 @@ -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -12,7 +13,8 @@ ERROR in ./index.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./index.js ModuleParseError +ERROR in ./index.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err index 801dff5a9a3e..c2f698b3883d 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/multi_json_syntax_error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./a.json × Json parsing error: Unexpected character } +ERROR in ./a.json + × Json parsing error: Unexpected character } ╭─[1:1] 1 │ { 2 │ "a" @@ -6,7 +7,8 @@ ERROR in ./a.json × Json parsing error: Unexpected character } · ─ ╰──── -ERROR in ./b.json × Json parsing error: Unexpected end of JSON +ERROR in ./b.json + × Json parsing error: Unexpected end of JSON ╭──── 1 │ "测试utf8/" · ▲ diff --git a/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err b/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err index 5a907147756f..9a46656cb21b 100644 --- a/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err +++ b/packages/rspack/tests/diagnostics/module-parse-failed/multiple_file_syntax_error/stats.err @@ -1,4 +1,5 @@ -ERROR in ./a.js ModuleParseError +ERROR in ./a.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -12,7 +13,8 @@ ERROR in ./a.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./a.js ModuleParseError +ERROR in ./a.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -27,7 +29,8 @@ ERROR in ./a.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./b.js ModuleParseError +ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -41,7 +44,8 @@ ERROR in ./b.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./b.js ModuleParseError +ERROR in ./b.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -56,7 +60,8 @@ ERROR in ./b.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./c.js ModuleParseError +ERROR in ./c.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -70,7 +75,8 @@ ERROR in ./c.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./c.js ModuleParseError +ERROR in ./c.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -85,7 +91,8 @@ ERROR in ./c.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./d.js ModuleParseError +ERROR in ./d.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -99,7 +106,8 @@ ERROR in ./d.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./d.js ModuleParseError +ERROR in ./d.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -114,7 +122,8 @@ ERROR in ./d.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./e.js ModuleParseError +ERROR in ./e.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -128,7 +137,8 @@ ERROR in ./e.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./e.js ModuleParseError +ERROR in ./e.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -143,7 +153,8 @@ ERROR in ./e.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./f.js ModuleParseError +ERROR in ./f.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -157,7 +168,8 @@ ERROR in ./f.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./f.js ModuleParseError +ERROR in ./f.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon @@ -172,7 +184,8 @@ ERROR in ./f.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./g.js ModuleParseError +ERROR in ./g.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expression expected @@ -186,7 +199,8 @@ ERROR in ./g.js ModuleParseError help: You may need an appropriate loader to handle this file type. -ERROR in ./g.js ModuleParseError +ERROR in ./g.js +ModuleParseError × Module parse failed: ╰─▶ × JavaScript parsing error: Expected a semicolon