Skip to content

Commit

Permalink
feat(devex): Refactor Venia to be portable and importable (#788)
Browse files Browse the repository at this point in the history
  • Loading branch information
zetlen authored and jimbo committed Jan 29, 2019
1 parent 20ff0d1 commit 441b648
Show file tree
Hide file tree
Showing 59 changed files with 422 additions and 137 deletions.
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Some fixture code breaks linting
__fixtures__
# Minified build assets
dist
# Babelified ES modules for NPM dependents
esm
# Devdocs is a separate project
pwa-devdocs
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ test-results.json
lerna-debug.log
.env
yarn-error.log
# Packages that build partially transpiled ES modules put them here
packages/*/esm/*
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Generated coverage pages
coverage
# Minified build assets
dist
# Babelified ES modules for NPM dependents
esm
# Devdocs is a separate project
pwa-devdocs
1 change: 1 addition & 0 deletions .yarnrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-prefix "~"
59 changes: 55 additions & 4 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const browsers = require('./browserslist');
const chalk = require('chalk');

const plugins = [
['@babel/plugin-proposal-class-properties'],
Expand All @@ -15,10 +16,59 @@ const targets = {
test: 'node 10'
};

const config = {
env: {
let warned = false;

const config = api => {
if (process.env.WARN_RESOLVE) {
warned = true;
console.warn(
chalk.bold.yellowBright(
'You may see some warnings that @magento/venia-drivers could not be resolved. This is normal and not an error; Venia exports a virtual import path and babel-plugin-module-resolver is hardcoded to warn about it.'
)
);
}
const envConfigs = {
/**
* Watch mode and build:esm partial transpilation mode.
* The module-resolver plugin makes Babel recognize import paths from
* package root, like 'src/classify'.
*/
development: {
plugins,
// Ignore __mocks__, __stories__, etc.
ignore: [/\/__\w+__\//],
plugins: [
...plugins,
[
'module-resolver',
{
root: ['./'],
/**
* Exported modules will be consumed by other projects
* which import Venia. Those projects will need to
* override the 'src/drivers' dependency so Venia
* modules will run outside the Venia app. This alias
* exports the modules so the drivers dependency is
* a unique string '@magento/venia-drivers', which is
* less likely to collide with an existing dependency
* than 'src/drivers' is.
*
* In webpack (or any build system) config for a project
* using Venia modules, you must write an override for
* '@magento/venia-drivers' and make an alias to that
* module in your build configuration, e.g.:
*
* alias: {
* '@magento/venia-drivers': './src/veniaDrivers'
* }
*
* to map from this virtual string to your replacement.
*/
alias: {
'^src/drivers$': '@magento/venia-drivers'
}
}
]
],
presets: [
['@babel/preset-env', { modules: false, targets: targets.dev }]
]
Expand All @@ -44,7 +94,8 @@ const config = {
]
]
}
}
};
return envConfigs[api.env() || 'development'];
};

module.exports = config;
13 changes: 5 additions & 8 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ const path = require('path');
*/

// Reusable glob string for building `testMatch` patterns.
const testGlob = '/**/__tests__/*.(test|spec).js';
// All testable code in packages lives at either 'src' for code that must
// transpile, or 'lib' for code that doesn't have to.
const testGlob = '/**/{src,lib}/**/__tests__/*.(test|spec).js';

const configureProject = (dir, displayName, cb) =>
// Defaults that every project config must include.
Expand Down Expand Up @@ -94,12 +96,6 @@ const jestConfig = {
// Expose jsdom to tests.
browser: true,
moduleNameMapper: {
// Peregrine imports a virtual module that must be mocked.
// It would be nice if Venia respected a mock in Peregrine,
// but it doesn't, so Venia tests will fail without this.
'^FETCH_ROOT_COMPONENT$': inPackage(
'__mocks__/virtualModule.js'
),
// Mock binary files to avoid excess RAM usage.
'\\.(jpg|jpeg|png)$': inPackage('__mocks__/fileMock.js'),
// CSS module classes are dynamically generated, but that makes
Expand All @@ -111,7 +107,7 @@ const jestConfig = {
// Re-write imports to Peregrine to ensure they're not pulled
// from the build artifacts on disk in `dist`.
'^@magento/peregrine(/*(?:.+)*)':
'<rootDir>/packages/peregrine/src/$1'
'<rootDir>/packages/peregrine/$1'
},
// Reproduce the Webpack resolution config that lets Venia import
// from `src` instead of with relative paths:
Expand Down Expand Up @@ -163,6 +159,7 @@ const jestConfig = {
// Don't look for test files in these directories.
testPathIgnorePatterns: [
'dist',
'esm',
'node_modules',
'__fixtures__',
'__helpers__',
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"lint": "eslint '@(packages|scripts)/**/{*.js,package.json}' --ignore-pattern node_modules --ignore-pattern storybook-dist",
"now-build": "cp packages/venia-concept/.env.dist packages/venia-concept/.env && yarn run build",
"now-start": "yarn run stage:venia",
"postbuild": "rimraf \"./packages/*/{esm,dist}/{,**/}__*__\"",
"prettier": "prettier --write '@(packages|scripts)/**/*.@(js|css)' '*.js'",
"prettier:validate": "prettier-check '@(packages|scripts)/**/*.@(js|css)' '*.js'",
"prettier:check": "prettier --list-different '@(packages|scripts)/**/*.@(js|css)' '*.js'",
Expand All @@ -45,6 +46,7 @@
"devDependencies": {
"@magento/eslint-config": "~1.3.0",
"babel-eslint": "~10.0.1",
"babel-plugin-module-resolver": "~3.1.3",
"bundlesize": "~0.17.1",
"chalk": "~2.4.2",
"chokidar": "~2.0.4",
Expand Down
16 changes: 11 additions & 5 deletions packages/peregrine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
},
"description": "The core runtime of Magento PWA",
"main": "dist/index.js",
"browser": "dist/index.js",
"scripts": {
"build": "babel src --out-dir dist --root-mode 'upward' --ignore '__tests__/,__mocks__/,__fixtures__/' --source-maps --copy-files",
"build:dev": "yarn build",
"clean": "rimraf dist",
"build": "concurrently --raw yarn:build:cjs yarn:build:esm",
"build:cjs": "BABEL_ENV=production babel src --out-dir dist --root-mode 'upward' --source-maps",
"build:dev": "yarn run build",
"build:esm": "BABEL_ENV=development babel src --out-dir esm --root-mode 'upward' --source-maps",
"clean": "rimraf dist esm",
"prepublishOnly": "yarn run clean && yarn run build",
"storybook": "start-storybook -p 9001 -c .storybook",
"storybook:build": "build-storybook -c .storybook -o storybook-dist",
Expand All @@ -33,6 +36,7 @@
"@babel/plugin-transform-runtime": "~7.2.0",
"@babel/runtime": "~7.2.0",
"@storybook/react": "~4.1.6",
"concurrently": "~4.1.0",
"intl": "~1.2.5",
"react": "~16.7.0",
"react-dom": "~16.7.0",
Expand All @@ -49,6 +53,8 @@
"node": ">=10.7.0",
"yarn": ">=1.12.0"
},
"module": "src/index.js",
"jsnext:main": "src/index.js"
"module": "esm/index.js",
"jsnext:main": "src/index.js",
"es2015": "src/index.js",
"sideEffects": false
}
13 changes: 11 additions & 2 deletions packages/peregrine/src/Router/MagentoRouteHandler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { Component } from 'react';
import { func, shape, string } from 'prop-types';

import fetchRootComponent from 'FETCH_ROOT_COMPONENT';
// 2019-01-28 Removed virtual `FETCH_ROOT_COMPONENT` import. It's much cleaner
// to inject a "fetchRootComponent" global at build time, so that's what we
// changed the MagentoRootComponentsPlugin to do.
import resolveUnknownRoute from './resolveUnknownRoute';

const InternalError = Symbol('InternalError');
Expand Down Expand Up @@ -77,6 +79,13 @@ export default class MagentoRouteHandler extends Component {
location: { pathname }
} = this.props;

// Depending on the environment, the fetchRootComponent global can be
// either an ES module with a `default` property or a plain CJS module.
const fetchRoot =
'default' in fetchRootComponent
? fetchRootComponent.default
: fetchRootComponent;

try {
// try to resolve the route
// if this throws, we essentially have a 500 Internal Error
Expand All @@ -95,7 +104,7 @@ export default class MagentoRouteHandler extends Component {

// at this point we should have a matching RootComponent
// if this throws, we essentially have a 500 Internal Error
const RootComponent = await fetchRootComponent(type);
const RootComponent = await fetchRoot(type);

// associate the matching RootComponent with this location
this.setRouteComponent(pathname, RootComponent, { id });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import React from 'react';
import MagentoRouteHandler from '../MagentoRouteHandler';
import { shallow } from 'enzyme';
import resolveUnknownRoute from '../resolveUnknownRoute';
import fetchRootComponent from 'FETCH_ROOT_COMPONENT';

jest.mock('FETCH_ROOT_COMPONENT', () => jest.fn(), { virtual: true });
const fetchRootComponent = (global.fetchRootComponent = jest.fn());

jest.mock('../resolveUnknownRoute');

Expand Down
2 changes: 2 additions & 0 deletions packages/pwa-buildpack/.babelrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const config = {
// Ignore __mocks__, __stories__, etc.
ignore: [/\/__\w+__\//],
plugins: [
['@babel/plugin-proposal-class-properties', { loose: false }],
['@babel/plugin-syntax-jsx'],
Expand Down
2 changes: 1 addition & 1 deletion packages/pwa-buildpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"description": "Build/Layout optimization tooling and Peregrine framework adapters for the Magento PWA",
"main": "dist/index.js",
"scripts": {
"build": "babel src --out-dir dist --root-mode 'root' --ignore '__tests__/,__mocks__/,__fixtures__/' --source-maps --copy-files",
"build": "babel src --out-dir dist --root-mode 'root' --source-maps --copy-files",
"build:dev": "yarn run build",
"clean": "rimraf dist",
"prebuild": "yarn run clean",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { readFile: fsReadFile } = require('fs');
const readFile = require('util').promisify(fsReadFile);
const { ProvidePlugin } = require('webpack');
const readdir = require('readdir-enhanced');
const directiveParser = require('@magento/directive-parser');
const VirtualModulePlugin = require('virtual-module-webpack-plugin');
Expand All @@ -23,10 +24,15 @@ class MagentoRootComponentsPlugin {
}

apply(compiler) {
// Provide `fetchRootComponent` as a global: Expose the source as a
// module, and then use a ProvidePlugin to inline it.
new VirtualModulePlugin({
moduleName: 'FETCH_ROOT_COMPONENT',
contents: this.contents
}).apply(compiler);
new ProvidePlugin({
fetchRootComponent: 'FETCH_ROOT_COMPONENT'
}).apply(compiler);
}

async buildFetchModule() {
Expand Down
6 changes: 5 additions & 1 deletion packages/venia-concept/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
web/
# Minified build assets
dist/
# Babelified ES modules for NPM dependents
esm/
# Generated coverage pages
coverage
20 changes: 15 additions & 5 deletions packages/venia-concept/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@
},
"description": "Venia PWA Concept Storefront for Magento 2",
"main": "src/index.js",
"browser": {
"@magento/venia-drivers": "src/drivers"
},
"bin": {
"venia": "./bin/venia.js"
},
"scripts": {
"build": "yarn run clean && yarn run validate-queries && yarn run build:prod",
"build": "yarn run clean && yarn run build:esm && yarn run validate-queries && yarn run build:prod",
"build:analyze": "yarn run clean && mkdir dist && yarn run validate-queries && yarn run build:stats",
"build:dev": "echo 'Skipping venia-concept build...'",
"build:esm": "BABEL_ENV=development WARN_RESOLVE=1 babel src --out-dir esm --root-mode 'upward' --source-maps --copy-files",
"build:prod": "webpack -p --color --progress --profile --env.mode production",
"build:stats": "webpack -p --color --progress --profile --env.mode production --json > dist/build-stats.json",
"clean": "rimraf dist",
"prebuild": "yarn run clean",
"clean": "rimraf dist esm",
"prepublishOnly": "yarn run build",
"start": "node server.js",
"start:debug": "node --inspect-brk ./node_modules/.bin/webpack-dev-server --progress --color --env.mode development",
"stats": "webpack-bundle-analyzer dist/build-stats.json",
Expand Down Expand Up @@ -93,5 +96,12 @@
"engines": {
"node": ">=10.7.0",
"yarn": ">=1.12.0"
}
},
"module": "esm/index.js",
"es2015": "src/index.js",
"esnext": "src/index.js",
"sideEffects": [
"./src/index.js",
"./src/**/*.css"
]
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { Component } from 'react';
import { string, number, shape } from 'prop-types';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { connect, Query } from 'src/drivers';

import classify from 'src/classify';
import { setCurrentPage, setPrevPageTotal } from 'src/actions/catalog';
Expand Down
3 changes: 1 addition & 2 deletions packages/venia-concept/src/RootComponents/Product/Product.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';
import { bool, shape, number, arrayOf, string } from 'prop-types';

import { connect, Query } from 'src/drivers';
import { addItemToCart } from 'src/actions/cart';
import { loadingIndicator } from 'src/components/LoadingIndicator';
import ProductFullDetail from 'src/components/ProductFullDetail';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { connect } from 'react-redux';
import { connect } from 'src/drivers';

import Search from './search';
import { executeSearch, toggleSearch } from 'src/actions/app';
Expand Down
3 changes: 1 addition & 2 deletions packages/venia-concept/src/RootComponents/Search/search.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import { Query } from 'react-apollo';
import { Query, Redirect } from 'src/drivers';
import { getSearchParams } from 'src/util/getSearchParams';
import { bool, func, object, shape, string } from 'prop-types';
import gql from 'graphql-tag';
Expand Down
2 changes: 1 addition & 1 deletion packages/venia-concept/src/components/App/container.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { connect } from 'react-redux';
import { connect } from 'src/drivers';

import { closeDrawer } from 'src/actions/app';
import App from './app';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { string, number, shape } from 'prop-types';
import { Query } from 'react-apollo';
import { Query } from 'src/drivers';
import classify from 'src/classify';
import { loadingIndicator } from 'src/components/LoadingIndicator';
import defaultClasses from './categoryList.css';
Expand Down
Loading

1 comment on commit 441b648

@vercel
Copy link

@vercel vercel bot commented on 441b648 Jan 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aliasing failed with the following error:

Error! Instance verification timed out (3m)

Please sign in to comment.