Skip to content

Commit

Permalink
2.0.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
JayCanuck committed Feb 12, 2019
2 parents 79f8350 + d4c8855 commit 7d8d819
Show file tree
Hide file tree
Showing 27 changed files with 7,922 additions and 9,634 deletions.
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,49 @@
## 2.0.0 (February 11, 2019)

Updated all dependencies to latest releases and added support for TypeScript. In keeping with community standards, CSS/LESS is now processed in the global scope, while modular CSS can be retained by using the `.module.css`/`.module.less` extension or setting the `forceCSSModules` Enact project setting in `package.json`.

### create

* Updated default included moonstone template for latest Enact with `.module.less` modular LESS naming format.

### link

* Improved handling and errors when linking into a non-Enact project.

### pack

* Refactored build procedure for latest Webpack 4 and Babel 7.
* Added support for stage-3 CSS via `postcss-preset-env`, with `custom-properties` temporarily disabled while a bug is being resolved.
* Added support for `.env` fileformat to declare environment variables for parsing/app-embedding.
* Added support for TypeScript compilation.
* Added opt-in support for TypeScript typechecking at buildtime (via `typescript` app-side dependency).
* Additional CSS optimization applied via `optimize-css-assets-webpack-plugin`.
* Modified Babel configuration to use built-in APIs rather than transpiling mini re-implementations.
* Modified CSS file handling to only process modular CSS on the `.module.css` extension.
* Modified LESS file handling to be independence (only running LESS files through the LESS compiler), with `.module.lesas` file extension enabled modular context.
* Switched from `less-plugin-resolution-independence` to `postcss-plugin-resolution-independence` to apply to both LESS and CSS build chains.
* Switched from `uglifyjs-webpack-plugin` to `terser-webpack-plugin` as Uglify is no longer actively developed.
* Switched from `extract-text-webpack-plugin` to `mini-css-extract-plugin` for CSS content output.
* Removed direct autoprefixer usage as `postcss-preset-env` contains embedded support.
* Removed support for `.__DEV__` CSS class and replaced it with `@__DEV__` LESS variable for usage as a CSS guard.
* Removed legacy custom browser targetting format and now following `browserslist` standard for desclaring supporting browsers.

### lint

* Added support for TSLint, when linting a TypeScript project and `tslint` is globally or locally installed.

### test

* Replaced Karma/PhantomJS/Mocha/DirtyChai testing stack with a Jest-based alternative implementation.
* Supports Jest options like `--watch` and `--coverage` as a result.
* Removed custom Enzyme webpack plugin since we can pre-setup Enyme directly for Jest usage.
* Removed Sinon in favour of Jest built-in mocking/spy functionality.

### transpile

* Added `--commonjs` option, enabled by default, which will convert all ES6 import/export statements into CommonJS.
* LESS files will now be transpiled into CSS. Directories named `style` will not transpile LESS and will just copy the files (useful for sharing LESS variables/mixins). Directories named `internal` within `styles` will be ignored.

## 1.2.1 (December 7, 2018)

* Fixed test execution failures where an old copy of Enzyme was erroring out on the latest React 1.6 releases.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ The @enact/cli tool will check the project's **package.json** looking for an opt
* `screenTypes` _[array|string]_ - Array of 1 or more screentype definitions to be used with prerender HTML initialization. Can alternatively reference a json filepath to read for screentype definitons. By default, will use any preset for a specified theme or fallback to moonstone.
* `nodeBuiltins` _[object]_ - Configuration settings for polyfilling NodeJS built-ins. See `node` [webpack option](https://webpack.js.org/configuration/node/).
* `externalStartup` _[boolean]_ - Flag whether to externalize the startup/update js that is normally inlined within prerendered app HTML output.
* `forceCSSModules` _[boolean]_ - Flag whether to force all LESS/CSS to be processed in a modular context (not just the `*.module.css` and `*.module.less` files).
* `deep` _[string|array]_ - 1 or more JavaScript conditions that, when met, indicate deeplinking and any prerender should be discarded.
* `target` _[string|array]_ - A build-type generic preset string (see `target` [webpack option](https://webpack.js.org/configuration/target/)) or alternatively a specific [browserlist array](https://github.com/ai/browserslist) of desired targets.
* `proxy` _[string]_ - Proxy target during project `serve` to be used within the [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware).
Expand Down Expand Up @@ -113,7 +114,7 @@ npm install -g eslint eslint-plugin-react eslint-plugin-babel babel-eslint eslin

Unless otherwise specified, all content, including all source code files and documentation files in this repository are:

Copyright (c) 2016-2018 LG Electronics
Copyright (c) 2016-2019 LG Electronics

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Expand Down
14 changes: 8 additions & 6 deletions commands/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ const assets = [
];
const internal = [
'@babel/plugin-transform-modules-commonjs',
'babel-plugin-transform-rename-import',
'glob',
'global-modules',
'less-plugin-npm-import',
'semver',
'tar',
'v8-compile-cache',
Expand All @@ -36,15 +38,15 @@ const enhanced = ['chalk', 'cross-spawn', 'filesize', 'fs-extra', 'minimist', 's
const content = ['@babel/polyfill', 'react', 'react-dom'];
const bareDeps = {rimraf: '^2.6.2'};
const bareTasks = {
serve: 'webpack-dev-server --hot --inline --config config/webpack.config.dev.js',
pack: 'webpack --config config/webpack.config.dev.js',
'pack-p': 'webpack --config config/webpack.config.prod.js',
watch: 'webpack --config config/webpack.config.dev.js --watch',
serve: 'webpack-dev-server --hot --inline --env development --config config/webpack.config.js',
pack: 'webpack --env development --config config/webpack.config.js',
'pack-p': 'webpack --env production --config config/webpack.config.js',
watch: 'webpack --env development --config config/webpack.config.js --watch',
clean: 'rimraf build dist',
lint: 'eslint --no-eslintrc --config enact --ignore-pattern config/* .',
license: 'license-checker ',
test: 'karma test start config/karma.conf.js --single-run',
'test-watch': 'karma test start config/karma.conf.js'
test: 'jest --config config/jest/jest.config.js',
'test-watch': 'jest --config config/jest/jest.config.js --watch'
};

function displayHelp() {
Expand Down
4 changes: 3 additions & 1 deletion commands/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ function api({verbose = false} = {}) {
}
}

if (missing.length === enact.length) {
if (enact.length === 0) {
reject(new Error('No Enact dependencies found within the package. Nothing to link.'));
} else if (missing.length === enact.length) {
reject(new Error('Unable to detect any Enact global modules. Please ensure they are linked correctly.'));
} else {
const proc = spawn('npm', linkArgs, {stdio: 'inherit', cwd: process.cwd()});
Expand Down
69 changes: 67 additions & 2 deletions commands/lint.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
/* eslint-env node, es6 */
const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const spawn = require('cross-spawn');
const glob = require('glob');
const minimist = require('minimist');
const resolver = require('resolve');
const {packageRoot} = require('@enact/dev-utils');

const globOpts = {
ignore: ['node_modules/**', 'build/**', 'dist/**'],
nodir: true
};

function displayHelp() {
let e = 'node ' + path.relative(process.cwd(), __filename);
Expand All @@ -24,7 +34,11 @@ function displayHelp() {
process.exit(0);
}

function api({strict = false, local = false, fix = false, eslintArgs = []} = {}) {
function shouldESLint() {
return glob.sync('**/*.+(js|jsx)', globOpts).length > 0;
}

function eslint({strict = false, local = false, fix = false, eslintArgs = []} = {}) {
let args = [];
if (strict) {
args.push('--no-eslintrc', '--config', require.resolve('eslint-config-enact/strict'));
Expand All @@ -41,7 +55,8 @@ function api({strict = false, local = false, fix = false, eslintArgs = []} = {})
args.push('.');
}
return new Promise((resolve, reject) => {
const child = cp.fork(require.resolve('eslint/bin/eslint'), args, {env: process.env, cwd: process.cwd()});
const opts = {env: process.env, cwd: process.cwd()};
const child = cp.fork(require.resolve('eslint/bin/eslint'), args, opts);
child.on('close', code => {
if (code !== 0) {
reject();
Expand All @@ -52,6 +67,56 @@ function api({strict = false, local = false, fix = false, eslintArgs = []} = {})
});
}

function tslintBin(context) {
try {
resolver.sync('tslint', {basedir: context});
return path.join(context, 'node_modules', '.bin', 'tslint');
} catch (e) {
return 'tslint';
}
}

function shouldTSLint(context) {
if (glob.sync('**/*.+(ts|tsx)', globOpts).length > 0) {
try {
return !spawn.sync(tslintBin(context), ['-v'], {stdio: 'ignore'}).error;
} catch (e) {
if (fs.existsSync(path.join(context, 'tslint.json'))) {
console.warn(
'TSLint config file found, however TSLint could not be resolved.\n' +
'Install TSLint globally or locally on this project to ' +
'enable TypeScript linting.'
);
}
}
}
return false;
}

function tslint({fix = false} = {}, context) {
const args = ['-p', context];
if (fix) args.push('--fix');

return new Promise((resolve, reject) => {
const opts = {env: process.env, cwd: process.cwd(), stdio: 'inherit'};
const child = spawn(tslintBin(context), args, opts);
child.on('close', code => {
if (code !== 0) {
reject();
} else {
resolve();
}
});
});
}

function api(opts) {
const context = packageRoot().path;
return Promise.resolve()
.then(() => shouldESLint() && eslint(opts))
.then(() => shouldTSLint(context) && tslint(opts, context));
}

function cli(args) {
const opts = minimist(args, {
boolean: ['local', 'strict', 'fix', 'help'],
Expand Down
38 changes: 16 additions & 22 deletions commands/pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function details(err, stats, output) {
stats.compilation.warnings.forEach(w => {
w.message = w.message.replace(/\n.* potentially fixable with the `--fix` option./gm, '');
});
const statsJSON = stats.toJson({}, true);
const statsJSON = stats.toJson({all: false, warnings: true, errors: true});
const messages = formatWebpackMessages(statsJSON);
if (messages.errors.length) {
return new Error(messages.errors.join('\n\n'));
Expand All @@ -78,7 +78,7 @@ function details(err, stats, output) {
);
return new Error(messages.warnings.join('\n\n'));
} else {
printFileSizes(statsJSON, output);
printFileSizes(stats, output);
console.log();
if (messages.warnings.length) {
console.log(chalk.yellow('Compiled with warnings:\n'));
Expand All @@ -100,15 +100,18 @@ function details(err, stats, output) {

// Print a detailed summary of build files.
function printFileSizes(stats, output) {
const assets = stats.assets.filter(asset => /\.(js|css|bin)$/.test(asset.name)).map(asset => {
const size = fs.statSync(path.join(output, asset.name)).size;
return {
folder: path.relative(app.context, path.join(output, path.dirname(asset.name))),
name: path.basename(asset.name),
size: size,
sizeLabel: filesize(size)
};
});
const assets = stats
.toJson({all: false, assets: true})
.assets.filter(asset => /\.(js|css|bin)$/.test(asset.name))
.map(asset => {
const size = fs.statSync(path.join(output, asset.name)).size;
return {
folder: path.relative(app.context, path.join(output, path.dirname(asset.name))),
name: path.basename(asset.name),
size: size,
sizeLabel: filesize(size)
};
});
assets.sort((a, b) => b.size - a.size);
const longestSizeLabelLength = Math.max.apply(null, assets.map(a => stripAnsi(a.sizeLabel).length));
assets.forEach(asset => {
Expand Down Expand Up @@ -163,10 +166,6 @@ function watch(config) {
}

function api(opts = {}) {
let config;

// Apply any package.json enact metadata overrides.
// Until webpak 4 is used, must occur before requiring webpack config.
if (opts.meta) {
let meta;
try {
Expand All @@ -178,13 +177,8 @@ function api(opts = {}) {
}

// Do this as the first thing so that any code reading it knows the right env.
if (opts.production) {
process.env.NODE_ENV = 'production';
config = require('../config/webpack.config.prod');
} else {
process.env.NODE_ENV = 'development';
config = require('../config/webpack.config.dev');
}
const configFactory = require('../config/webpack.config');
const config = configFactory(opts.production ? 'production' : 'development');

// Set any output path override
if (opts.output) config.output.path = path.resolve(opts.output);
Expand Down
14 changes: 6 additions & 8 deletions commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const openBrowser = require('react-dev-utils/openBrowser');
const {choosePort, createCompiler, prepareProxy, prepareUrls} = require('react-dev-utils/WebpackDevServerUtils');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const app = require('@enact/dev-utils').optionParser;
const {optionParser: app} = require('@enact/dev-utils');

// Any unhandled promise rejections should be treated like errors.
process.on('unhandledRejection', err => {
Expand All @@ -34,8 +34,8 @@ console.log = (log => (data, ...rest) =>
typeof data === 'undefined'
? log()
: typeof data === 'string'
? log(data.replace(/npm run build/, 'npm run pack-p'), ...rest)
: log.call(this, data, ...rest))(console.log);
? log(data.replace(/npm run build/, 'npm run pack-p'), ...rest)
: log.call(this, data, ...rest))(console.log);

function displayHelp() {
let e = 'node ' + path.relative(process.cwd(), __filename);
Expand Down Expand Up @@ -151,7 +151,7 @@ function serve(config, host, port, open) {
const urls = prepareUrls(protocol, host, resolvedPort);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, config, app.name, urls);
compiler.plugin('after-emit', (compilation, callback) => {
compiler.hooks.afterEmit.tapAsync('EnactCLI', (compilation, callback) => {
compilation.warnings.forEach(w => {
if (w.message) {
// Remove any --fix ESLintinfo messages since the eslint-loader config is
Expand Down Expand Up @@ -193,8 +193,6 @@ function serve(config, host, port, open) {
}

function api(opts) {
// Apply any package.json enact metadata overrides.
// Until webpak 4 is used, must occur before requiring webpack config.
if (opts.meta) {
let meta;
try {
Expand All @@ -206,7 +204,8 @@ function api(opts) {
}

// Setup the development config with additional webpack-dev-erver customizations.
const config = hotDevServer(require('../config/webpack.config.dev'));
const configFactory = require('../config/webpack.config');
const config = hotDevServer(configFactory('development'));

// Tools like Cloud9 rely on this.
const host = process.env.HOST || opts.host || config.devServer.host || '0.0.0.0';
Expand All @@ -229,7 +228,6 @@ function cli(args) {
if (opts.help) displayHelp();

process.chdir(app.context);
process.env.NODE_ENV = 'development';

api(opts).catch(err => {
console.error(chalk.red('ERROR: ') + (err.message || err));
Expand Down
Loading

0 comments on commit 7d8d819

Please sign in to comment.