Skip to content

Commit

Permalink
Enhancement/issue 426 plugin babel (#481)
Browse files Browse the repository at this point in the history
* initial example of a babel plugin

* babel working with babel

* ignore test file

* set default value for babelHelpers

* set peer deps for plugin-postcss and plugin-babel

* WIP babel preset env

* babel preset env working

* add default test case

* minor cleanup

* minor cleanup

* extendConfig refactoring and specs

* improve export map detection and force ESM support from Babel

* test cases and refactoring for postcss

* config look refactor

* enable preset env for postcss and update docs

* grammar

* grammar and punctuation

* delete obsolete test case

* restore eject command and specs and docs

* remove example code from www
  • Loading branch information
thescientist13 committed Apr 3, 2021
1 parent e79a373 commit 3b82fb3
Show file tree
Hide file tree
Showing 41 changed files with 2,114 additions and 288 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
**/public/**
**/node_modules/**
!.eslintrc.js
!.mocharc.js
!.mocharc.js
packages/plugin-babel/test/cases/**/*main.js
6 changes: 0 additions & 6 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
// const path = require('path');

module.exports = {
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module'
// TODO should we use this?
// babelOptions: {
// configFile: path.join(__dirname, './packages/cli/src/config/babel.config.js')
// }
},
env: {
browser: true,
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ Then in your _package.json_, you can run the CLI like so:
"scripts": {
"build": "greenwood build",
"start": "greenwood develop",
"serve": "greenwood serve",
"eject": "greenwood eject"
"serve": "greenwood serve"
}
```

- `greenwood build`: Generates a production build of your project
- `greenwood develop`: Starts a local development server for your project
- `greenwood serve`: Generates a production build of the project and serves it locally on a simple web server.
- `greenwood eject`: Ejects configurations to your working directory for additional customizations.

## Documentation
All of our documentation is on our [website](https://www.greenwoodjs.io/) (which itself is built by Greenwood!). See our website documentation to learn more about:
Expand Down
28 changes: 14 additions & 14 deletions packages/cli/src/commands/eject.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
const fs = require('fs');
const generateCompilation = require('../lifecycles/compile');
const path = require('path');

module.exports = ejectConfigFiles = async (copyAllFiles) => {
module.exports = ejectConfiguration = async () => {
return new Promise(async (resolve, reject) => {
try {
const compilation = await generateCompilation();
const configFilePaths = fs.readdirSync(path.join(__dirname, '../config'));

if (copyAllFiles) {
configFilePaths = fs.readdirSync(path.join(__dirname, '../config'));
} else {
// TODO
configFilePaths = [
'webpack.config.common.js',
'webpack.config.develop.js',
'webpack.config.prod.js'
];
}
configFilePaths.forEach(configFile => {
fs.copyFileSync(path.join(__dirname, '../config', configFile), path.join(process.cwd(), configFile));
console.log(`Ejecting ${configFile}`.blue);
configFilePaths.forEach((configFile) => {
const from = path.join(__dirname, '../config', configFile);
const to = `${compilation.context.projectDirectory}/${configFile}`;

fs.copyFileSync(from, to);

console.log(`Ejected ${configFile} successfully.`);
});

console.debug('all configuration files ejected.');

resolve();
} catch (err) {
reject(err);
Expand Down
3 changes: 0 additions & 3 deletions packages/cli/src/config/.browserslistrc

This file was deleted.

13 changes: 4 additions & 9 deletions packages/cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const program = require('commander');
const runProductionBuild = require('./commands/build');
const runDevServer = require('./commands/develop');
const runProdServer = require('./commands/serve');
// const ejectConfigFiles = require('./tasks/eject');
const ejectConfiguration = require('./commands/eject');
const greenwoodPackageJson = require('../package.json');

let cmdOption = {};
Expand Down Expand Up @@ -90,15 +90,10 @@ const run = async() => {
await runProdServer();

break;
// TODO
// case 'eject'
// console.log('Ejecting configurations'.yellow);
case 'eject':
await ejectConfiguration();

// await ejectConfigFiles(cmdOption.all);

// console.log(`Configurations ejected successfully to ${process.cwd()}`.green);

// break;
break;
default:
console.warn(`
Error: not able to detect command. try using the --help flag if
Expand Down
86 changes: 70 additions & 16 deletions packages/cli/src/plugins/resource/plugin-node-modules.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Detects and fully resolves requests to node_modules.
* Detects and fully resolves requests to node_modules and handles creating an importMap.
*
*/
const acorn = require('acorn');
Expand All @@ -11,16 +11,17 @@ const walk = require('acorn-walk');

const importMap = {};

// https://nodejs.org/api/packages.html#packages_determining_module_system
const getPackageEntryPath = (packageJson) => {
let entry = packageJson.module
? packageJson.module // favor ESM entry points first
: packageJson.main
? packageJson.main
: 'index.js';

// use .mjs version of it exists, for packages like redux
if (fs.existsSync(`${process.cwd()}/node_modules/${packageJson.name}/${entry.replace('.js', '.mjs')}`)) {
: packageJson.exports // next favor export maps
? Object.keys(packageJson.exports)
: packageJson.main // then favor main
? packageJson.main
: 'index.js'; // lastly, fallback to index.js

// use .mjs version if it exists, for packages like redux
if (!Array.isArray(entry) && fs.existsSync(`${process.cwd()}/node_modules/${packageJson.name}/${entry.replace('.js', '.mjs')}`)) {
entry = entry.replace('.js', '.mjs');
}

Expand Down Expand Up @@ -78,16 +79,69 @@ const walkPackageJson = (packageJson = {}) => {
const dependencyPackageJsonPath = path.join(dependencyPackageRootPath, 'package.json');
const dependencyPackageJson = require(dependencyPackageJsonPath);
const entry = getPackageEntryPath(dependencyPackageJson);
const packageEntryPointPath = path.join(process.cwd(), './node_modules', dependency, entry);
const packageEntryModule = fs.readFileSync(packageEntryPointPath, 'utf-8');
const isJavascriptPackage = packageEntryPointPath.endsWith('.js') || packageEntryPointPath.endsWith('.mjs');
const isJavascriptPackage = Array.isArray(entry) || typeof entry === 'string' && entry.endsWith('.js') || entry.endsWith('.mjs');

if (isJavascriptPackage) {
walkModule(packageEntryModule, dependency);

importMap[dependency] = `/node_modules/${dependency}/${entry}`;

walkPackageJson(dependencyPackageJson);

// https://nodejs.org/api/packages.html#packages_determining_module_system
if (Array.isArray(entry)) {
// we have an exportMap
const exportMap = entry;

exportMap.forEach((entry) => {
const exportMapEntry = dependencyPackageJson.exports[entry];
let packageExport;

if (Array.isArray(exportMapEntry)) {
let fallbackPath;
let esmPath;

exportMapEntry.forEach((mapItem) => {
switch (typeof mapItem) {

case 'string':
fallbackPath = mapItem;
break;
case 'object':
const entryTypes = Object.keys(mapItem);

if (entryTypes.import) {
esmPath = entryTypes.import;
} else if (entryTypes.require) {
console.error('The package you are importing needs commonjs support. Please use our commonjs plugin to fix this error.');
fallbackPath = entryTypes.require;
} else if (entryTypes.default) {
console.warn('The package you are requiring may need commonjs support. If this module is not working for you, consider adding our commonjs plugin.');
fallbackPath = entryTypes.default;
}
break;
default:
console.warn(`Sorry, we were unable to detect the module type for ${mapItem} :(. please consider opening an issue to let us know about your use case.`);
break;

}
});

packageExport = esmPath
? esmPath
: fallbackPath;
} else if ((exportMapEntry.endsWith('.js') || exportMapEntry.endsWith('.mjs')) && exportMapEntry.indexOf('*') < 0) {
// is not an export array, or package.json, or wildcard
packageExport = exportMapEntry;
}

if (packageExport) {
importMap[`${dependency}/${entry.replace('./', '')}`] = `/node_modules/${dependency}/${packageExport.replace('./', '')}`;
}
});
} else {
const packageEntryPointPath = path.join(process.cwd(), './node_modules', dependency, entry);
const packageEntryModule = fs.readFileSync(packageEntryPointPath, 'utf-8');

walkModule(packageEntryModule, dependency);
importMap[dependency] = `/node_modules/${dependency}/${entry}`;
walkPackageJson(dependencyPackageJson);
}
}
});
};
Expand Down
20 changes: 0 additions & 20 deletions packages/cli/test/cases/build.config.babel/babel.config.js

This file was deleted.

This file was deleted.

3 changes: 0 additions & 3 deletions packages/cli/test/cases/build.config.babel/src/pages/index.md

This file was deleted.

Loading

0 comments on commit 3b82fb3

Please sign in to comment.