Skip to content

Commit

Permalink
Merge pull request #395 from reactioncommerce/feat-aldeed-modules
Browse files Browse the repository at this point in the history
feat: output mjs modules to enable tree shaking
  • Loading branch information
aldeed authored Feb 12, 2019
2 parents fd534b3 + 9bae595 commit e4e4322
Show file tree
Hide file tree
Showing 10 changed files with 370 additions and 198 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ node_modules
reports/*
**/package-lock.json
dist
dist-modules-temp

styleguide/build/
styleguide/favicon.ico
styleguide/favicon.png
styleguide/fonts/
styleguide/index.html
styleguide/manifest.json
styleguide/reaction-design-system-logo.svg
styleguide/reaction-design-system-logo.svg
62 changes: 58 additions & 4 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,54 @@
// See https://babeljs.io/docs/en/config-files#root-babelconfigjs-files
module.exports = function (api) {
api.cache(true);
const isTest = api.env("test");

// Config for when running Jest tests
if (isTest) {
return {
presets: [
[
"@babel/env",
{
// https://babeljs.io/docs/en/babel-preset-env#targets
targets: {
node: "current",
browsers: [
"last 2 versions",
"ie 11"
]
}
}
],
"@babel/preset-react"
],
plugins: [
"babel-plugin-styled-components",
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }],
"@babel/plugin-syntax-dynamic-import"
]
};
}

// We set this in the `build:modules` package.json script
const esmodules = process.env.BABEL_MODULES === "1";

const presets = [
[
"@babel/env",
{
modules: esmodules ? false : "auto",
// https://babeljs.io/docs/en/babel-preset-env#targets
targets: {
node: "current",
node: "8",
browsers: [
"last 2 versions",
"ie 11"
]
],
// "browsers" target is ignored when "esmodules" is true
esmodules
},
// https://babeljs.io/docs/en/babel-preset-env#usebuiltins-usage-experimental
useBuiltIns: "usage"
}
],
Expand All @@ -23,10 +59,28 @@ module.exports = function (api) {
"babel-plugin-styled-components",
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }],
"@babel/plugin-syntax-dynamic-import"
"@babel/plugin-syntax-dynamic-import",
[
"@babel/plugin-transform-runtime",
{
useESModules: esmodules
}
]
];

let ignore;
if (process.env.NODE_ENV === "production") {
ignore = [
"**/*.test.js",
"__snapshots__",
"**/setupTests.js",
"**/tests",
"**/scripts"
];
}

return {
ignore,
presets,
plugins,
sourceMaps: true
Expand Down
18 changes: 10 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"node"
],
"reporters": [
"default",
"jest-junit"
],
"setupFiles": [
Expand All @@ -73,11 +74,11 @@
"<rootDir>/package/src/setupTests.js"
],
"testPathIgnorePatterns": [
"/config/",
"/node_modules/",
"/reports/",
"/package/dist/",
"/package/node_modules/"
"<rootDir>/config/",
"<rootDir>/node_modules/",
"<rootDir>/reports/",
"<rootDir>/package/dist/",
"<rootDir>/package/node_modules/"
],
"transform": {
"^.+\\.jsx?$": "./babel.jest.js"
Expand All @@ -88,8 +89,8 @@
"suiteName": "jest-tests"
},
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@reactioncommerce/components-context": "^1.2.0",
"babel-polyfill": "^6.26.0",
"prop-types": "15.6.2",
"react": "16.4.2",
"react-container-query": "^0.11.0",
Expand All @@ -111,6 +112,7 @@
"@babel/plugin-proposal-throw-expressions": "7.2.0",
"@babel/plugin-syntax-dynamic-import": "7.2.0",
"@babel/plugin-syntax-import-meta": "7.2.0",
"@babel/plugin-transform-runtime": "7.2.0",
"@babel/preset-env": "7.3.1",
"@babel/preset-react": "^7.0.0",
"@commitlint/cli": "7.0.0",
Expand All @@ -120,7 +122,7 @@
"autoprefixer": "7.1.6",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "24.0.0",
"babel-jest": "24.1.0",
"babel-loader": "7.1.2",
"babel-plugin-module-resolver": "3.1.3",
"babel-plugin-rewire-exports": "1.0.1",
Expand Down Expand Up @@ -148,7 +150,7 @@
"html-webpack-plugin": "2.29.0",
"husky": "1.0.0-rc.9",
"ignore-loader": "^0.1.2",
"jest": "24.0.0",
"jest": "24.1.0",
"jest-junit": "6.1.0",
"jest-styled-components": "6.3.1",
"object-assign": "4.1.1",
Expand Down
13 changes: 9 additions & 4 deletions package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
},
"license": "Apache-2.0",
"private": false,
"sideEffects": false,
"scripts": {
"prebuild": "rimraf dist && node ./scripts/prebuild.js",
"build": "BABEL_ENV=production babel --root-mode upward src --out-dir dist --ignore **/*.test.js,__snapshots__,*/setupTests.js,*/tests",
"prebuild": "rimraf dist && rimraf dist-modules-temp && node ./scripts/prebuild.js",
"build": "npm run build:common && npm run build:modules",
"build:common": "BABEL_ENV=production babel --root-mode upward src --out-dir dist",
"build:modules": "BABEL_ENV=production BABEL_MODULES=1 babel --root-mode upward src --out-dir dist-modules-temp",
"postbuild": "BABEL_ENV=production babel-node --root-mode upward ./scripts/postbuild.js",
"release": "npm run build && npm publish dist"
},
"dependencies": {
"@babel/runtime": "^7.3.1",
"@material-ui/core": "^3.1.0",
"accounting-js": "^1.1.1",
"lodash.debounce": "^4.0.8",
Expand All @@ -42,13 +46,14 @@
"@babel/plugin-proposal-throw-expressions": "7.2.0",
"@babel/plugin-syntax-dynamic-import": "7.2.0",
"@babel/plugin-syntax-import-meta": "7.2.0",
"@babel/plugin-transform-runtime": "7.2.0",
"@babel/preset-env": "7.3.1",
"@babel/preset-react": "^7.0.0",
"@reactioncommerce/eslint-config": "1.9.0",
"autoprefixer": "7.1.6",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "24.0.0",
"babel-jest": "24.1.0",
"babel-loader": "7.1.2",
"babel-plugin-module-resolver": "3.1.3",
"babel-plugin-rewire-exports": "1.0.1",
Expand All @@ -68,7 +73,7 @@
"eslint-plugin-promise": "4.0.1",
"eslint-plugin-react": "7.12.4",
"fs-extra": "^5.0.0",
"jest": "24.0.0",
"jest": "24.1.0",
"jest-junit": "6.1.0",
"jest-styled-components": "6.3.1",
"object-assign": "4.1.1",
Expand Down
62 changes: 53 additions & 9 deletions package/scripts/postbuild.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
/* eslint-disable no-console */
/* Much of this is borrowed from https://github.com/mui-org/material-ui/blob/master/packages/material-ui/scripts/copy-files.js */
/* Some of this is borrowed from https://github.com/mui-org/material-ui/blob/master/packages/material-ui/scripts/copy-files.js */

import path from "path";
import fse from "fs-extra";
import replaceInFiles from "replace-in-files";
const path = require("path");
const fse = require("fs-extra");
const replaceInFiles = require("replace-in-files");

const DIST_FOLDER = path.join(process.cwd(), "dist");
const DIST_MODULES_FOLDER = path.join(process.cwd(), "dist-modules-temp");
const COMPONENTS_FOLDER = path.join(DIST_FOLDER, "components");

/**
* @summary Recursively changes all files with one extension to another
* @param {String} fullDirPath Directory path
* @param {String} ext Extension to look for
* @param {String} newExt Extension to change to
* @returns {Promise<undefined>} Nothing
*/
async function recursivelyChangeExtension(fullDirPath, ext, newExt) {
const directoryContents = await fse.readdir(fullDirPath);
const promises = directoryContents.map(async (item) => {
const childPath = path.join(fullDirPath, item);
if (item.indexOf(".") === -1) return recursivelyChangeExtension(childPath, ext, newExt);

if (!item.endsWith(`.${ext}`)) return null;

await fse.copy(childPath, childPath.replace(`.${ext}`, `.${newExt}`));
await fse.remove(childPath);
});
await Promise.all(promises);
}

/**
* @summary Copies a file to the build directory
* @param {String} file File path
Expand All @@ -28,8 +50,8 @@ async function createPackageFile() {
const { devDependencies, jest, scripts, ...packageDataOther } = JSON.parse(packageData);
const newPackageData = {
...packageDataOther,
main: "./index.js"
// module: "./index.es.js"
main: "index",
module: "index.mjs"
};
const buildPath = path.resolve(__dirname, "../dist/package.json");
const stringPackageJson = JSON.stringify(newPackageData, null, 2);
Expand All @@ -47,19 +69,41 @@ async function createPackageFile() {
* @returns {Promise<undefined>} Nothing
*/
async function replaceUtilsPathForComponent(componentFolderPath) {
return replaceInFiles({
await replaceInFiles({
files: `${componentFolderPath}/**/*.js`,
from: /\.\.\/\.\.\/utils/g,
to: "../utils"
});

await replaceInFiles({
files: `${componentFolderPath}/**/*.mjs`,
from: /\.\.\/\.\.\/utils/g,
to: "../utils"
});
}

/**
* @summary The main post-build script
* @summary The main post-build script.
* 1. Rename all `.js` files in `dist-modules-temp` to `.mjs` extension
* 2. Copy all `.mjs` files into `dist`
* 3. Delete `dist-modules-temp`
* 4. Move components up to `dist` root and delete `components` folder
* 5. Copy `package.json` and markdown files into `dist`
*
* `dist` is now ready to be published in the final package structure
* @returns {Promise<undefined>} Nothing
*/
async function run() {
// After the Babel build step, we have a `dist` folder but we want to remove the extra `components`
// Rename all `.js` files in `dist-modules-temp` to `.mjs` extension
await recursivelyChangeExtension(DIST_MODULES_FOLDER, "js", "mjs");

// Copy all `.mjs` files into `dist`
await fse.copy(DIST_MODULES_FOLDER, DIST_FOLDER);

// Delete `dist-modules-temp`
await fse.remove(DIST_MODULES_FOLDER);

// We now have a `dist` folder but we want to remove the extra `components`
// folder inside it in order to have flatter import paths. We"ll traverse the `dist/components/*`
// folders here and move them up a level.
const directoryContents = await fse.readdir(COMPONENTS_FOLDER);
Expand Down
12 changes: 12 additions & 0 deletions package/scripts/prebuild.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
/**
* This script auto-creates an `index.js` file in each components/Component/v*
* directory. It runs just before we do the Babel build for publishing.
*/

const path = require("path");
const fs = require("fs-extra");

const SRC_PATH = path.join(process.cwd(), "src");
const BASE_PATH = path.join(SRC_PATH, "components");

// Loop through each item in the /package/src/components directory
const directoryContents = fs.readdirSync(BASE_PATH);
directoryContents.forEach((componentName) => {
// Ignore files
if (componentName.indexOf(".") !== -1) return;

// For directories, loop through each item in them
const compDirectoryContents = fs.readdirSync(path.join(BASE_PATH, componentName));
compDirectoryContents.forEach((versionName) => {
// Ignore anything that isn't a version directory
if (!versionName.startsWith("v")) return;

// In all version directories, auto-create an index.js file if there isn't one
const filePath = path.join(BASE_PATH, componentName, versionName, "index.js");
fs.ensureFileSync(filePath);
fs.writeFileSync(filePath, `export { default } from "./${componentName}";\n`);
Expand Down
Loading

0 comments on commit e4e4322

Please sign in to comment.