Skip to content

Commit

Permalink
Merge pull request #18220 from storybookjs/improve/detection-webpack5
Browse files Browse the repository at this point in the history
CLI: Improve webpack version and add detection of nextjs
  • Loading branch information
shilman committed May 18, 2022
2 parents 152e441 + 95a5c80 commit 0a6e347
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 20 deletions.
53 changes: 53 additions & 0 deletions lib/cli/src/detect-nextjs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { detectNextJS } from './detect-nextjs';

test('detect nothing if it fails', () => {
const out = detectNextJS({
type: 'npm',
executeCommand: () => {
throw new Error('test error');
},
});
expect(out).toEqual(false);
});

test('detect from npm ls', () => {
const outputFromCommand = `
/path/to/cwd
└── next@12.0.7
`;
const out = detectNextJS({ type: 'npm', executeCommand: () => outputFromCommand });
expect(out).toEqual(12);
});

test('detect from npm why', () => {
const outputFromCommand = `
next@12.0.7
node_modules/next
next@"^12.0.7" from the root project
peer next@">=10.2.0" from eslint-config-next@12.0.7
node_modules/eslint-config-next
dev eslint-config-next@"^12.0.7" from the root project
`;
const out = detectNextJS({ type: 'npm', executeCommand: () => outputFromCommand });
expect(out).toEqual(12);
});

test('detect from yarn why', () => {
const outputFromCommand = `
yarn why v1.22.18
[1/4] 🤔 Why do we have the module "next"...?
[2/4] 🚚 Initialising dependency graph...
[3/4] 🔍 Finding dependency...
[4/4] 🚡 Calculating file sizes...
=> Found "next@12.0.7"
info Has been hoisted to "next"
info This module exists because it's specified in "dependencies".
info Disk size without dependencies: "XX.XXMB"
info Disk size with unique dependencies: "XX.XXMB"
info Disk size with transitive dependencies: "XX.XXMB"
info Number of shared dependencies: XXX
✨ Done in 0.XXs.
`;
const out = detectNextJS({ type: 'npm', executeCommand: () => outputFromCommand });
expect(out).toEqual(12);
});
30 changes: 30 additions & 0 deletions lib/cli/src/detect-nextjs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { JsPackageManager } from './js-package-manager';

const regex = /[\s"\n]next.*?(\d+).*/;

export const detectNextJS = (
packageManager: Pick<JsPackageManager, 'type' | 'executeCommand'>
): number | false => {
try {
let out = '';
if (packageManager.type === 'npm') {
try {
// npm <= v7
out = packageManager.executeCommand('npm', ['ls', 'next']);
} catch (e2) {
// npm >= v8
out = packageManager.executeCommand('npm', ['why', 'next']);
}
} else {
out = packageManager.executeCommand('yarn', ['why', 'next']);
}

const [, version] = out.match(regex);

return version && parseInt(version, 10) ? parseInt(version, 10) : false;
} catch (err) {
//
}

return false;
};
32 changes: 32 additions & 0 deletions lib/cli/src/detect-webpack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { JsPackageManager } from './js-package-manager';

export const detectWebpack = (packageManager: JsPackageManager): number | false => {
try {
let out = '';
if (packageManager.type === 'npm') {
try {
// npm <= v7
out = packageManager.executeCommand('npm', ['ls', 'webpack']);
} catch (e2) {
// npm >= v8
out = packageManager.executeCommand('npm', ['why', 'webpack']);
}
} else {
out = packageManager.executeCommand('yarn', ['why', 'webpack']);
}

// if the user has BOTH webpack 4 and 5 installed already, we'll pick the safest options (4)
if (out.includes('webpack@4') || out.includes('webpack@npm:4')) {
return 4;
}

// the user has webpack 4 installed, but not 5
if (out.includes('webpack@5') || out.includes('webpack@npm:5')) {
return 5;
}
} catch (err) {
//
}

return false;
};
32 changes: 12 additions & 20 deletions lib/cli/src/detect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
} from './project_types';
import { getBowerJson, paddedLog } from './helpers';
import { PackageJson, readPackageJson, JsPackageManager } from './js-package-manager';
import { detectWebpack } from './detect-webpack';
import { detectNextJS } from './detect-nextjs';

const viteConfigFiles = ['vite.config.ts', 'vite.config.js', 'vite.config.mjs'];

Expand Down Expand Up @@ -112,31 +114,21 @@ export function detectBuilder(packageManager: JsPackageManager) {
return CoreBuilder.Vite;
}

try {
let out = '';
if (packageManager.type === 'npm') {
try {
// npm <= v7
out = packageManager.executeCommand('npm', ['ls', 'webpack']);
} catch (e2) {
// npm >= v8
out = packageManager.executeCommand('npm', ['why', 'webpack']);
}
} else {
out = packageManager.executeCommand('yarn', ['why', 'webpack']);
}

// if the user has BOTH webpack 4 and 5 installed already, we'll pick the safest options (4)
if (out.includes('webpack@4') || out.includes('webpack@npm:4')) {
const nextJSVersion = detectNextJS(packageManager);
if (nextJSVersion) {
if (nextJSVersion >= 11) {
return CoreBuilder.Webpack5;
}
}

// the user has webpack 4 installed, but not 5
if (out.includes('webpack@5') || out.includes('webpack@npm:5')) {
const webpackVersion = detectWebpack(packageManager);
if (webpackVersion) {
if (webpackVersion <= 4) {
return CoreBuilder.Webpack4;
}
if (webpackVersion >= 5) {
return CoreBuilder.Webpack5;
}
} catch (err) {
//
}

// Fallback to webpack4
Expand Down

0 comments on commit 0a6e347

Please sign in to comment.