Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dev-server): add managed paths #7713

Merged
merged 29 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
297a656
find & add the managed paths of the workspace
leimonio Jul 28, 2023
3c636af
log errors from webpack & webpack dev server
leimonio Jul 28, 2023
dbf42ce
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Jul 28, 2023
477b576
update naming & chnage to private member
leimonio Jul 31, 2023
5b204d4
register on component add and remove
leimonio Jul 31, 2023
354b008
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Jul 31, 2023
564c8ab
update & use of packages excluder component
leimonio Aug 3, 2023
4b354dc
rename format to target
leimonio Aug 3, 2023
5191b2e
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 3, 2023
657307a
fix linting
leimonio Aug 3, 2023
233883b
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 3, 2023
2b1191f
Merge branch 'master' into feat/add-managed-paths
GiladShoham Aug 8, 2023
75c8a52
fix buil compilation issue
leimonio Aug 8, 2023
f902f60
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 8, 2023
86b00eb
Merge branch 'master' into feat/add-managed-paths
leimonio Aug 10, 2023
aad877d
update composition & docs
leimonio Aug 10, 2023
db37996
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 10, 2023
98c3a50
Merge branch 'master' into feat/add-managed-paths
leimonio Aug 11, 2023
ef833df
Merge branch 'master' into feat/add-managed-paths
GiladShoham Aug 14, 2023
887b799
Merge branch 'master' into feat/add-managed-paths
GiladShoham Aug 14, 2023
7316a0f
Merge branch 'master' into feat/add-managed-paths
leimonio Aug 15, 2023
8fb073a
Merge branch 'master' into feat/add-managed-paths
GiladShoham Aug 17, 2023
29dc2c8
move set component paths regexs to happen on pre start slot
GiladShoham Aug 17, 2023
8df9255
Merge branch 'master' into feat/add-managed-paths
GiladShoham Aug 17, 2023
bf671e4
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 17, 2023
f0782bb
fix with defaults
leimonio Aug 17, 2023
629b082
Merge branch 'master' of github.com:teambit/bit into feat/add-managed…
leimonio Aug 17, 2023
b252c53
Merge branch 'master' into feat/add-managed-paths
leimonio Aug 18, 2023
99a3ce0
Merge branch 'master' into feat/add-managed-paths
leimonio Aug 18, 2023
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
3 changes: 0 additions & 3 deletions scopes/compilation/bundler/dev-server.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ export class DevServerService implements EnvService<ComponentServer, DevServerDe
name = 'dev server';

constructor(
/**
* browser runtime slot
*/
private pubsub: PubsubMain,

private dependencyResolver: DependencyResolverMain,
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
type generateNodeModulesPatternOptions = {
export enum PatternTarget {
/**
* Used in Jest `transformIgnorePatterns` options
*/
JEST = 'jest',
/**
* Used in Webpack `snapshot.managedPaths` options
*/
WEBPACK = 'webpack',
}

type GenerateNodeModulesPatternOptions<T> = {
/**
* An array of packages name to exclude in the regex.
*/
Expand All @@ -8,30 +19,62 @@ type generateNodeModulesPatternOptions = {
* A component package looks like `@org/scope.namespace.component-name`.
*/
excludeComponents?: boolean;
/**
* The target for which patterns are generated.
*/
target?: T;
};

const patternTargetMap = {
[PatternTarget.JEST]: toJestPattern,
[PatternTarget.WEBPACK]: toWebpackPattern,
};

type PatternTargetMap = typeof patternTargetMap;
type PatternReturnType<T extends PatternTarget> = ReturnType<PatternTargetMap[T]>;

/**
* A function that receives an array of packages names and returns a pattern (string) of a regex that matches any node_modules/package-name except the provided package-names.
* @param {string[]} packages - array of packages.
* @returns {string} node modules catched packages regex.
*/
export function generateNodeModulesPattern({
packages = [],
excludeComponents,
}: generateNodeModulesPatternOptions): string {
const negativeLookaheadPatterns = packages.reduce((acc: string[], curr) => {
const yarnPattern = curr;
const pnpmCurr = curr.replace(/\//g, '\\+');
const pnpmPattern = `\\.pnpm/(.*[+/])?${pnpmCurr}.*`;
export function generateNodeModulesPattern<T extends PatternTarget>(
options: GenerateNodeModulesPatternOptions<T> = {}
): PatternReturnType<T> {
const { packages = [], excludeComponents, target = PatternTarget.JEST } = options;
const negativeLookaheadPatterns = packages.reduce((acc: string[], packageName) => {
const yarnPattern = packageName.replace(/\//g, '[\\/]');
const pnpmPackageName = packageName.replace(/\//g, '\\+');
const pnpmPattern = `\\.pnpm[\\/](.*[+\\/])?${pnpmPackageName}.*`;
return [...acc, yarnPattern, pnpmPattern];
}, []);

if (excludeComponents) {
negativeLookaheadPatterns.push(
'@[^/]+/([^/]+\\.)+[^/]+',
'\\.pnpm/(.+[+/])?@[^+]+\\+([^+]+\\.)+[^+]+',
'\\.pnpm/.+/node_modules/@[^/]+/([^/]+\\.)+[^/]+'
);
}
const transformIgnorePattern = `node_modules/(?!(${negativeLookaheadPatterns.join('|')})/)`;
return transformIgnorePattern;

return patternTargetMap[target](negativeLookaheadPatterns) as PatternReturnType<T>;
}

function toJestPattern(patterns: string[]) {
return `node_modules/(?!(${patterns.join('|')})/)`;
}

/**
* Webpack managed paths evaluate absolutes paths to `package.json` files.
* We need to generate a pattern that excludes the `package.json` files of the bit component packages.
* Example:
* - Component package: `@my-org/my-scope.components`
* - Webpack path: `/Users/aUser/dev/bit-example/node_modules/@my-org/my-scope.components/package.json`
* - RegExp to exclude this path from managed paths: `/^(.+?[\\/]node_modules[\\/](?!(@my-org[\\/]my-scope.components))(@.+?[\\/])?.+?)[\\/]/`
*/

function toWebpackPattern(patterns: string[]) {
return patterns.map((pattern) => {
return `^(.+?[\\/]node_modules[\\/](?!(${pattern}))(@.+?[\\/])?.+?)[\\/]`;
});
}
2 changes: 1 addition & 1 deletion scopes/dependencies/modules/packages-excluder/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { generateNodeModulesPattern } from './generate-node-modules-pattern';
export { generateNodeModulesPattern, PatternTarget } from './generate-node-modules-pattern';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
import { generateNodeModulesPattern } from './generate-node-modules-pattern';
import { PatternTarget, generateNodeModulesPattern } from './generate-node-modules-pattern';

export function LiveExample() {
const [text, setText] = useState('react,@myorg,some-lib');
Expand All @@ -18,14 +18,29 @@ export function RegexExample() {
const [packagesToExclude, setPackagesToExclude] = useState('@myorg,react,some-lib');
const [packageToCheck, setPackageToCheck] = useState('@myorg');
const [excludeComponents, setExcludeComponents] = useState(false);
const [calculatedRegex, setCalculatedRegex] = useState('');
const [regexResult, setRegexResult] = useState(true);
const [defaultCalculatedRegex, setDefaultCalculatedRegex] = useState('');
const [webpackCalculatedRegexps, setWebpackCalculatedRegexps] = useState([]);
const [defaultRegexResult, setDefaultRegexResult] = useState(true);
const [webpackRegexResult, setWebpackRegexResult] = useState(true);

useEffect(() => {
const pattern = generateNodeModulesPattern({ packages: packagesToExclude.split(','), excludeComponents });
setCalculatedRegex(pattern);
const pattern = generateNodeModulesPattern({ packages: packagesToExclude.split(','), excludeComponents }) as string;
const webpackPatterns = generateNodeModulesPattern({
packages: packagesToExclude.split(','),
excludeComponents,
target: PatternTarget.WEBPACK,
});
setDefaultCalculatedRegex(pattern);
// @ts-ignore
setWebpackCalculatedRegexps(webpackPatterns);
const regex = new RegExp(pattern);
setRegexResult(regex.test(`node_modules/${packageToCheck}/some-path`));
const webpackRegexps = webpackPatterns.map((webpackPattern) => new RegExp(webpackPattern));
setDefaultRegexResult(regex.test(`node_modules/${packageToCheck}/some-path`));
setWebpackRegexResult(
webpackRegexps.every((webpackRegex) =>
webpackRegex.test(`Users/aUser/workspace-a/node_modules/${packageToCheck}/package.json`)
)
);
}, [packagesToExclude, packageToCheck, excludeComponents]);

return (
Expand All @@ -38,19 +53,39 @@ export function RegexExample() {
/>
<div>Exclude components:</div>
<input type="checkbox" checked={excludeComponents} onChange={(e) => setExcludeComponents(e.target.checked)} />
<div>Write a package that you want to check with Regex test:</div>
<div style={{ marginBottom: 12 }}>
<input value="node_modules/" disabled />
<input value={packageToCheck} onChange={(e) => setPackageToCheck(e.target.value)} />
<input value="/some-path" disabled />
</div>
<div style={{ backgroundColor: '#ededed', padding: 8 }}>
regex exclude {packageToCheck} excludeComponents: {excludeComponents.toString()}
<br />
regex: {calculatedRegex}
<br />
result: {regexResult.toString()}
</div>

<section>
<h3>Default target (Jest)</h3>
<div>Write a package that you want to check with Regex test:</div>
<div style={{ marginBottom: 12 }}>
<input value="node_modules/" disabled />
<input value={packageToCheck} onChange={(e) => setPackageToCheck(e.target.value)} />
<input value="/some-path" disabled />
</div>
<div style={{ backgroundColor: '#ededed', padding: 8 }}>
regex exclude {packageToCheck} excludeComponents: {excludeComponents.toString()}
<br />
regex: {defaultCalculatedRegex}
<br />
result: {defaultRegexResult.toString()}
</div>
</section>
<section>
<h3>Target Webpack</h3>
<div>Write a package that you want to check with Regex test:</div>
<div style={{ marginBottom: 12 }}>
<input value="Users/aUser/workspace-a/node_modules/" disabled />
<input value={packageToCheck} onChange={(e) => setPackageToCheck(e.target.value)} />
<input value="/package.json" disabled />
</div>
<div style={{ backgroundColor: '#ededed', padding: 8 }}>
regex exclude {packageToCheck} excludeComponents: {excludeComponents.toString()}
<br />
regex: {webpackCalculatedRegexps}
<br />
result: {webpackRegexResult.toString()}
</div>
</section>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ labels: ['typescript', 'utils', 'packages', 'node modules', 'node', 'regex', 'ex
description: 'Create node modules regex with packages.'
---

import { generateNodeModulesPattern } from './generate-node-modules-pattern';
import { generateNodeModulesPattern, PatternTarget } from './generate-node-modules-pattern';

A function that returns a pattern (string) of a regex that matches any `node_modules/package-name` except the ones that we want to exclude.

> **_NOTE:_** There are different cases of patterns that need to be generated. This depends on different capture groups that might need to be applied. At the moment matching patterns based on the target are supported. Check `target` option for details.

Options:

- `packages` - **string[]** - optional. A list of package names and package scopes that we want to exclude.
- `excludeComponents` - **boolean** - optional. If set to `true`, all component packages are excluded.
- `target` - **enum** - optional. Specifies the target for which patterns need to be generated for. Default target `PatternTarget.JEST`.
- Available pattern targets through `PatternTarget` enum:
- `JEST`: Used in Jest `transformIgnorePatterns` options
- `WEBPACK`: Used in Webpack `snapshot.managedPaths` options

Basic example:

Expand All @@ -21,6 +27,15 @@ Basic example:
};
```

Basic example for `PatternTarget.WEBPACK` target:

```js live
() => {
const packagesToTransform = ['@my-scope/my-button-component'];
return generateNodeModulesPattern({ packages: packagesToTransform, target: PatternTarget.WEBPACK });
};
```

Regex exclude the package:

```js live
Expand All @@ -32,6 +47,19 @@ Regex exclude the package:
};
```

Regex exclude the package for `PatternTarget.WEBPACK` target:

```js live
() => {
const packagesToTransform = ['@my-scope/my-button-component'];
const patterns = generateNodeModulesPattern({ packages: packagesToTransform, target: PatternTarget.WEBPACK });
const regexps = patterns.map((pattern) => new RegExp(pattern));
return regexps
.every((regex) => regex.test('Users/aUser/dev/node_modules/@my-scope/my-button-component/package.json'))
.toString();
};
```

Regex not exclude the package:

```js live
Expand All @@ -43,6 +71,19 @@ Regex not exclude the package:
};
```

Regex not exclude the package for `PatternTarget.WEBPACK` target:

```js live
() => {
const packagesToTransform = ['@my-scope/my-button-component'];
const patterns = generateNodeModulesPattern({ packages: packagesToTransform, target: PatternTarget.WEBPACK });
const regexps = patterns.map((pattern) => new RegExp(pattern));
return regexps
.some((regex) => regex.test('Users/aUser/dev/node_modules/not-excluded-package/package.json'))
.toString();
};
```

Exclude components:

```js live
Expand Down
5 changes: 3 additions & 2 deletions scopes/harmony/application/build-application.task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ export class AppsBuildTask implements BuildTask {
appResult.componentResult.warnings || []
);
// @ts-ignore
merged.componentResult._metadata.buildDeployContexts = // @ts-ignore
(merged.componentResult._metadata.buildDeployContexts || [])
merged.componentResult._metadata.buildDeployContexts = ( // @ts-ignore
merged.componentResult._metadata.buildDeployContexts || []
)
// @ts-ignore
.concat(appResult.componentResult._metadata || []);
});
Expand Down
7 changes: 7 additions & 0 deletions scopes/webpack/webpack/config/webpack.dev.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function configFactory(
entryFiles: string[],
publicRoot: string,
publicPath: string,
componentPathsRegExps: RegExp[],
pubsub: PubsubMain,
title?: string,
favicon?: string
Expand Down Expand Up @@ -72,6 +73,7 @@ export function configFactory(

stats: {
errorDetails: true,
logging: 'error',
},

devServer: {
Expand Down Expand Up @@ -107,6 +109,7 @@ export function configFactory(

client: {
overlay: false,
logging: 'error',
},

setupMiddlewares: (middlewares, devServer) => {
Expand Down Expand Up @@ -160,6 +163,10 @@ export function configFactory(
}),
],

snapshot: {
...(componentPathsRegExps && componentPathsRegExps.length > 0 ? { managedPaths: componentPathsRegExps } : {}),
},

watchOptions: {
poll: true,
},
Expand Down
13 changes: 12 additions & 1 deletion scopes/webpack/webpack/webpack.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export class WebpackMain {
context.id,
context.rootPath,
context.publicPath,
this.workspace.getComponentPathsRegExps(),
context.title
) as any;
const wdsPath = webpackDevServerModulePath || require.resolve('webpack-dev-server');
Expand Down Expand Up @@ -197,9 +198,19 @@ export class WebpackMain {
devServerID: string,
publicRoot: string,
publicPath: string,
componentPathsRegExps: RegExp[],
title?: string
) {
return devServerConfigFactory(devServerID, rootPath, entry, publicRoot, publicPath, this.pubsub, title);
return devServerConfigFactory(
devServerID,
rootPath,
entry,
publicRoot,
publicPath,
componentPathsRegExps,
this.pubsub,
title
);
}

static slots = [];
Expand Down
2 changes: 1 addition & 1 deletion scopes/workspace/watcher/output-formatter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OnComponentEventResult } from '@teambit/workspace';
import chalk from 'chalk';

const verboseComponentFilesArrayToString = (componentFiles) => {
const verboseComponentFilesArrayToString = (componentFiles = []) => {
return componentFiles.reduce((outputString, filePath) => `${outputString} \t - ${filePath}\n`, ``);
};

Expand Down
3 changes: 3 additions & 0 deletions scopes/workspace/workspace/workspace.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ export default async function provideWorkspace(

const workspaceSchema = getWorkspaceSchema(workspace, graphql);
ui.registerUiRoot(new WorkspaceUIRoot(workspace, bundler));
ui.registerPreStart(async () => {
return workspace.setComponentPathsRegExps();
});
graphql.register(workspaceSchema);
const capsuleCmd = getCapsulesCommands(isolator, scope, workspace);
const commands: CommandList = [new EjectConfCmd(workspace), capsuleCmd, new UseCmd(workspace)];
Expand Down
Loading