Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ test/**/bin/
test/**/binary/
test/**/index.js
test/typescript/webpack.config.ts
test/config/error/syntax-error.js
test/config/error-array/webpack.config.js
test/config/error-commonjs/syntax-error.js
test/config/error-mjs/syntax-error.mjs
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ test/**/dist/
test/**/bin/
test/**/binary/
test/**/index.js
test/config/error/syntax-error.js
test/config/error-commonjs/syntax-error.js
test/config/error-mjs/syntax-error.mjs
packages/webpack-cli/__tests__/test-assets/.yo-rc.json
test/build-errors/stats.json
32 changes: 27 additions & 5 deletions packages/webpack-cli/lib/webpack-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,40 @@ class WebpackCLI {
constructor() {}

async resolveConfig(args) {
const loadConfig = (configPath) => {
const loadConfig = async (configPath) => {
const ext = extname(configPath);
const interpreted = Object.keys(jsVariants).find((variant) => variant === ext);

if (interpreted) {
rechoir.prepare(extensions, configPath);
}

let options;
const { pathToFileURL } = require('url');

let importESM;

try {
options = require(configPath);
importESM = new Function('id', 'return import(id);');
} catch (e) {
importESM = null;
}

let options;
try {
try {
options = require(configPath);
} catch (error) {
if (pathToFileURL && importESM && error.code === 'ERR_REQUIRE_ESM') {
const urlForConfig = pathToFileURL(configPath);

options = await importESM(urlForConfig);
options = options.default;

return { options, path: configPath };
}

throw error;
}
} catch (error) {
logger.error(`Failed to load '${configPath}'`);
logger.error(error);
Expand Down Expand Up @@ -90,7 +112,7 @@ class WebpackCLI {
process.exit(2);
}

const loadedConfig = loadConfig(configPath);
const loadedConfig = await loadConfig(configPath);

return evaluateConfig(loadedConfig, args);
}),
Expand Down Expand Up @@ -135,7 +157,7 @@ class WebpackCLI {
}

if (foundDefaultConfigFile) {
const loadedConfig = loadConfig(foundDefaultConfigFile.path);
const loadedConfig = await loadConfig(foundDefaultConfigFile.path);
const evaluatedConfig = await evaluateConfig(loadedConfig, args);

config.options = evaluatedConfig.options;
Expand Down
1 change: 1 addition & 0 deletions test/config-format/mjs/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('You know who');
18 changes: 18 additions & 0 deletions test/config-format/mjs/mjs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { run } = require('../../utils/test-utils');

describe('webpack cli', () => {
it('should support mjs config format', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.mjs'], false, [], { DISABLE_V8_COMPILE_CACHE: true });

if (exitCode === 0) {
expect(exitCode).toBe(0);
expect(stderr).toContain('Compilation starting...');
expect(stderr).toContain('Compilation finished');
expect(stdout).toBeTruthy();
} else {
expect(exitCode).toBe(2);
expect(/Cannot use import statement outside a module/.test(stderr) || /Unexpected token/.test(stderr)).toBe(true);
expect(stdout).toBeFalsy();
}
});
});
11 changes: 11 additions & 0 deletions test/config-format/mjs/webpack.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { fileURLToPath } from 'url';
import path from 'path';

export default {
mode: 'production',
entry: './main.js',
output: {
path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'dist'),
filename: 'foo.bundle.js',
},
};
33 changes: 33 additions & 0 deletions test/config/defaults/mjs-config/default-mjs-config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const fs = require('fs');
const path = require('path');
const { run, isWebpack5 } = require('../../../utils/test-utils');

describe('Default Config:', () => {
it('Should be able to pick mjs config by default', () => {
const { exitCode, stderr, stdout } = run(__dirname, [], false, [], { DISABLE_V8_COMPILE_CACHE: true });

if (exitCode === 0) {
expect(exitCode).toEqual(0);
expect(stderr).toContain('Compilation starting...');
expect(stderr).toContain('Compilation finished');
// default entry should be used
expect(stdout).toContain('./src/index.js');
// should pick up the output path from config
expect(stdout).toContain('test-output');

if (!isWebpack5) {
expect(stdout).toContain('Hash');
expect(stdout).toContain('Version');
expect(stdout).toContain('Built at');
expect(stdout).toContain('Time');
}

// check that the output file exists
expect(fs.existsSync(path.join(__dirname, '/dist/test-output.js'))).toBeTruthy();
} else {
expect(exitCode).toEqual(2);
expect(stderr).toContain('Unexpected token');
expect(stdout).toBeFalsy();
}
});
});
1 change: 1 addition & 0 deletions test/config/defaults/mjs-config/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Jotaro Kujo")
6 changes: 6 additions & 0 deletions test/config/defaults/mjs-config/webpack.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
mode: 'development',
output: {
filename: 'test-output.js',
},
};
File renamed without changes.
25 changes: 25 additions & 0 deletions test/config/error-mjs/config-error.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
const { resolve } = require('path');
const { run } = require('../../utils/test-utils');

describe('config error', () => {
it('should throw error with invalid configuration', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.mjs')], false, [], {
DISABLE_V8_COMPILE_CACHE: true,
});

expect(exitCode).toBe(2);
expect(/Invalid configuration object/.test(stderr) || /Unexpected token/.test(stderr)).toBe(true);
expect(stdout).toBeFalsy();
});

it('should throw syntax error and exit with non-zero exit code', () => {
const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'syntax-error.mjs')], false, [], {
DISABLE_V8_COMPILE_CACHE: true,
});

expect(exitCode).toBe(2);
expect(stderr).toContain('SyntaxError: Unexpected token');
expect(stdout).toBeFalsy();
});
});
1 change: 1 addition & 0 deletions test/config/error-mjs/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('config error test');
5 changes: 5 additions & 0 deletions test/config/error-mjs/syntax-error.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
name: 'config-error',
mode: 'development',
target: 'node'; //SyntaxError: Unexpected token ';'
};
5 changes: 5 additions & 0 deletions test/config/error-mjs/webpack.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
name: 'config-error',
mode: 'unknown', //error
target: 'node',
};