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

Add support for babel transform in monorepos #8651

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 64 additions & 0 deletions packages/core/integration-tests/test/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,69 @@ describe('babel', function () {
assert.strictEqual(output.default, 123);
});


it('should compile with different babel plugins in monorepos using js', async function () {
let b = await bundle(
path.join(__dirname, '/integration/babel-monorepos/packages/app/index.js'),
);

let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');
assert(!file.includes('class Test'));
assert(!file.includes('REPLACE_ME'));
assert(!file.includes('#private'));
assert(file.includes('---app---'));
assert(file.includes('---component---'));

let output = await run(b);
assert.strictEqual(typeof output, 'object');
assert.strictEqual(output.default, '---app---:---component---');
});

it('should compile with different babel plugins in monorepos using jsx', async function () {
let b = await bundle(
path.join(__dirname, '/integration/babel-monorepos/packages/app/jsx.js'),
);

let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');
assert(!file.includes('REPLACE_ME'));
assert(file.includes('React.createElement'));
assert(file.includes('---app---'));
assert(file.includes('---component---'));
});

it('should compile with different babel plugins in monorepos using typescript', async function () {
let b = await bundle(
path.join(__dirname, '/integration/babel-monorepos/packages/app/ts.ts'),
);

let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');

assert(!file.includes('class Test'));
assert(!file.includes('REPLACE_ME'));
assert(!file.includes('#private'));
assert(!file.includes('interface'));
assert(file.includes('---app---'));
assert(file.includes('---component---'));

let output = await run(b);
assert.strictEqual(typeof output, 'object');
assert.strictEqual(output.default, '---app---:---component---');
});

it('should compile with different babel plugins in monorepos using tsx', async function () {
let b = await bundle(
path.join(__dirname, '/integration/babel-monorepos/packages/app/tsx.tsx'),
);

let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');

assert(!file.includes('REPLACE_ME'));
assert(!file.includes('interface'));
assert(file.includes('React.createElement'));
assert(file.includes('---app---'));
assert(file.includes('---component---'));
});

it('should compile with custom babel plugin plus default transforms', async function () {
let b = await bundle(
path.join(__dirname, '/integration/babel-custom/index.js'),
Expand All @@ -547,6 +610,7 @@ describe('babel', function () {
);

let file = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');

assert(!file.includes('REPLACE_ME'));
assert(file.includes('React.createElement'));
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "babel-monorepos",
"workspaces": [
"packages/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["../babel-plugins/babel-plugin-app"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import componentFunc from '../component/index.js'

class Test {
classProperty = 2;
#privateProperty;

constructor(text, func) {
this.#privateProperty = text + ':' + func();
}

get() {
return this.#privateProperty;
}
}

export default new Test('REPLACE_ME', componentFunc).get();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Component from '../component/jsx'

export function Test() {
let text = 'REPLACE_ME';
return <div>{text}:<Component /></div>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "babel-monorepos-app",
"dependencies": {
"react": "*"
},
"browserslist": ">= 0.25%"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import componentFunc from '../component/ts'

class Test {
classProperty = 2;
#privateProperty;

constructor(text, func) {
this.#privateProperty = text + ':' + func();
}

get() {
return this.#privateProperty;
}
}

export default new Test('REPLACE_ME', componentFunc).get();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Component from '../component/tsx'

export function Test() {
let text = 'REPLACE_ME';
return <div>{text}:<Component /></div>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = () => {
return {
visitor: {
StringLiteral(path, state) {
const opts = state.opts;

if (path.node.value === 'REPLACE_ME') {
path.node.value = '---app---';
}
}
}
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = () => {
return {
visitor: {
StringLiteral(path, state) {
const opts = state.opts;

if (path.node.value === 'REPLACE_ME') {
path.node.value = '---component---';
}
}
}
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["../babel-plugins/babel-plugin-component"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function() {
return "REPLACE_ME";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function() {
let text = 'REPLACE_ME';
return <div>{text}</div>;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "babel-monorepos-component",
"dependencies": {
"react": "*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default function(): string {
return "REPLACE_ME";
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function() {
const text = "REPLACE_ME";
return <div>{text}</div>;
}

30 changes: 28 additions & 2 deletions packages/transformers/babel/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import type {BabelConfig} from './types';

import json5 from 'json5';
import path from 'path';
import fs from 'fs';
import {hashObject, relativePath, resolveConfig} from '@parcel/utils';
import {md, generateJSONCodeHighlights} from '@parcel/diagnostic';
import {BABEL_CORE_RANGE} from './constants';

import isJSX from './jsx';
import getFlowOptions from './flow';
import {enginesToBabelTargets} from './utils';
import type { FilePath } from "../../../core/types/index";

const TYPESCRIPT_EXTNAME_RE = /\.tsx?$/;
const JS_EXTNAME_RE = /^\.(js|cjs|mjs)$/;
Expand Down Expand Up @@ -55,14 +57,19 @@ export async function load(
});
}

// In a monorepos babel can't find .babelrc for depencies if they
// are siblings to the entrypoint package. This prevents Parceljs
// from applying Babel transforms to sibling packages during development.
const cwd = resolveCurrentWorkingDirectory(config, options);

// Do nothing if we cannot resolve any babel config filenames. Checking using our own
// config resolution (which is cached) is much faster than relying on babel.
if (
!(await resolveConfig(
options.inputFS,
config.searchPath,
BABEL_CONFIG_FILENAMES,
options.projectRoot,
cwd,
))
) {
return buildDefaultBabelConfig(options, config);
Expand All @@ -87,7 +94,7 @@ export async function load(
config.invalidateOnEnvChange('NODE_ENV');
let babelOptions = {
filename: config.searchPath,
cwd: options.projectRoot,
cwd,
envName:
options.env.BABEL_ENV ??
options.env.NODE_ENV ??
Expand Down Expand Up @@ -410,4 +417,23 @@ async function getCodeHighlights(fs, filePath, redundantPresets) {
},
},
];
}function resolveCurrentWorkingDirectory(
config: Config,
options: PluginOptions,
): string | FilePath {
let cwd;
if (!config.searchPath.startsWith(options.projectRoot)) {
// This is probably a mono repos with development packages, set cwd to package root
let pathArr = config.searchPath.split(path.sep);
pathArr.pop();
while (pathArr.length > 0 && !cwd) {
if (fs.existsSync([...pathArr, "package.json"].join(path.sep))) {
cwd = pathArr.join(path.sep);
}
pathArr.pop();
}
}

// If this isn't a package, return the original projectRoot
return cwd || options.projectRoot;
}