Browse Source

Upgrading to webpack-chain v3, add more tests for full presets

v5.0.0-beta
Eli Perelman 8 years ago
parent
commit
49b9e296ff
  1. 5
      package.json
  2. 14
      packages/neutrino-middleware-banner/index.js
  3. 9
      packages/neutrino-middleware-chunk/index.js
  4. 4
      packages/neutrino-middleware-clean/index.js
  5. 22
      packages/neutrino-middleware-compile-loader/index.js
  6. 3
      packages/neutrino-middleware-compile-loader/package.json
  7. 1602
      packages/neutrino-middleware-compile-loader/yarn.lock
  8. 8
      packages/neutrino-middleware-copy/index.js
  9. 5
      packages/neutrino-middleware-env/index.js
  10. 66
      packages/neutrino-middleware-eslint/index.js
  11. 1
      packages/neutrino-middleware-eslint/package.json
  12. 4
      packages/neutrino-middleware-eslint/yarn.lock
  13. 11
      packages/neutrino-middleware-font-loader/index.js
  14. 2
      packages/neutrino-middleware-hot/index.js
  15. 4
      packages/neutrino-middleware-html-loader/index.js
  16. 30
      packages/neutrino-middleware-html-template/index.js
  17. 3
      packages/neutrino-middleware-html-template/package.json
  18. 1568
      packages/neutrino-middleware-html-template/yarn.lock
  19. 11
      packages/neutrino-middleware-image-loader/index.js
  20. 3
      packages/neutrino-middleware-loader-merge/index.js
  21. 2
      packages/neutrino-middleware-minify/index.js
  22. 2
      packages/neutrino-middleware-named-modules/index.js
  23. 2
      packages/neutrino-middleware-progress/index.js
  24. 3
      packages/neutrino-middleware-progress/package.json
  25. 1687
      packages/neutrino-middleware-progress/yarn.lock
  26. 2
      packages/neutrino-middleware-start-server/index.js
  27. 4
      packages/neutrino-middleware-style-loader/index.js
  28. 45
      packages/neutrino-preset-airbnb-base/index.js
  29. 57
      packages/neutrino-preset-jest/src/index.js
  30. 16
      packages/neutrino-preset-karma/index.js
  31. 2
      packages/neutrino-preset-mocha/src/index.js
  32. 33
      packages/neutrino-preset-node/index.js
  33. 23
      packages/neutrino-preset-node/test/web_test.js
  34. 12
      packages/neutrino-preset-react/index.js
  35. 23
      packages/neutrino-preset-react/test/web_test.js
  36. 30
      packages/neutrino-preset-web/index.js
  37. 23
      packages/neutrino-preset-web/test/web_test.js
  38. 8
      packages/neutrino/bin/neutrino
  39. 3
      packages/neutrino/package.json
  40. 17
      packages/neutrino/src/neutrino.js
  41. 12
      packages/neutrino/test/api_test.js
  42. 6
      packages/neutrino/yarn.lock
  43. 718
      yarn.lock

5
package.json

@ -13,7 +13,7 @@
"deps:add": "oao add",
"deps:remove": "oao remove",
"deps:upgrade": "oao upgrade",
"deps:clean": "rm -rf packages/**/node_modules",
"deps:clean": "oao clean",
"docs:build": "gitbook build && cp CNAME _book",
"docs:deploy": "yarn docs:build && gh-pages --dist _book --remote upstream",
"docs:serve": "gitbook serve",
@ -31,6 +31,7 @@
"gitbook-plugin-github": "^2.0.0",
"gitbook-plugin-npmsearchlist": "^1.0.0",
"gitbook-plugin-prism": "^2.1.0",
"oao": "^0.7.2"
"oao": "^0.7.2",
"webpack": "^2.2.1"
}
}

14
packages/neutrino-middleware-banner/index.js

@ -1,8 +1,12 @@
const { BannerPlugin } = require('webpack');
const merge = require('deepmerge');
module.exports = ({ config }, options) => config.plugin('banner', BannerPlugin, merge({
banner: `require('source-map-support').install();`,
raw: true,
entryOnly: true
}, options));
module.exports = ({ config }, options) => config
.plugin('banner')
.use(BannerPlugin, [
merge({
banner: `require('source-map-support').install();`,
raw: true,
entryOnly: true
}, options)
]);

9
packages/neutrino-middleware-chunk/index.js

@ -1,7 +1,8 @@
const { CommonsChunkPlugin } = require('webpack').optimize;
const merge = require('deepmerge');
module.exports = ({ config }, options) => config.plugin('chunk', CommonsChunkPlugin, merge({
minChunks: Infinity,
names: ['vendor', 'manifest']
}, options));
module.exports = ({ config }, options) => config
.plugin('chunk')
.use(CommonsChunkPlugin, [
merge({ minChunks: Infinity, names: ['vendor', 'manifest'] }, options)
]);

4
packages/neutrino-middleware-clean/index.js

@ -4,5 +4,7 @@ const merge = require('deepmerge');
module.exports = ({ config }, options) => {
const { paths, root } = merge({ paths: [], root: process.cwd() }, options);
config.plugin('clean', CleanPlugin, paths, { root });
config
.plugin('clean')
.use(CleanPlugin, [paths, { root }]);
};

22
packages/neutrino-middleware-compile-loader/index.js

@ -1,5 +1,17 @@
module.exports = ({ config }, options) => config.module
.rule('compile')
.test(/\.jsx?$/)
.include(...options.include)
.loader('babel', require.resolve('babel-loader'), options.babel);
module.exports = ({ config }, options) => {
const rule = config.module
.rule('compile')
.test(options.test || /\.jsx?$/)
.use('babel')
.loader(require.resolve('babel-loader'))
.options(options.babel)
.end();
if (options.include) {
rule.include.merge(options.include);
}
if (options.exclude) {
rule.exclude.merge(options.exclude);
}
};

3
packages/neutrino-middleware-compile-loader/package.json

@ -16,7 +16,8 @@
"bugs": "https://github.com/mozilla-neutrino/neutrino-dev/issues",
"dependencies": {
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2"
"babel-loader": "^6.3.2",
"webpack": "^2.2.1"
},
"peerDependencies": {
"neutrino": "^5.0.0"

1602
packages/neutrino-middleware-compile-loader/yarn.lock

File diff suppressed because it is too large

8
packages/neutrino-middleware-copy/index.js

@ -1,8 +1,10 @@
const CopyPlugin = require('copy-webpack-plugin');
const merge = require('deepmerge');
module.exports = ({ config }, options) => {
const opts = merge({ patterns: [], options: {} }, options);
module.exports = ({ config }, opts) => {
const { patterns, options } = merge({ patterns: [], options: {} }, opts);
config.plugin('copy', CopyPlugin, opts.patterns, opts.options);
config
.plugin('copy')
.use(CopyPlugin, [patterns, options]);
};

5
packages/neutrino-middleware-env/index.js

@ -1,4 +1,5 @@
const { EnvironmentPlugin } = require('webpack');
module.exports = ({ config }, envs = []) => config.plugin('env', EnvironmentPlugin,
['NODE_ENV', ...(Array.isArray(envs) ? envs : [])]);
module.exports = ({ config }, envs = []) => config
.plugin('env')
.use(EnvironmentPlugin, ['NODE_ENV', ...(Array.isArray(envs) ? envs : [])]);

66
packages/neutrino-middleware-eslint/index.js

@ -7,41 +7,51 @@ const MODULES = join(__dirname, 'node_modules');
module.exports = (neutrino, options) => {
const { config } = neutrino;
const lint = config.module.rule('lint');
config.resolve.modules.add(MODULES);
config.resolveLoader.modules.add(MODULES);
config.module
.rule('lint')
lint
.test(options.test || /\.(js|jsx)$/)
.pre()
.include(options.include)
.loader('eslint', require.resolve('eslint-loader'), merge({
failOnError: IF_NOT_DEV,
emitWarning: IF_NOT_DEV,
emitError: IF_NOT_DEV,
cwd: process.cwd(),
useEslintrc: false,
root: true,
plugins: ['babel'],
baseConfig: {},
envs: ['es6'],
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2017,
sourceType: 'module',
ecmaFeatures: {
objectLiteralDuplicateProperties: false,
generators: true,
impliedStrict: true
}
},
settings: {},
globals: ['process'],
rules: {}
}, options.eslint || {}));
.use('eslint')
.loader(require.resolve('eslint-loader'))
.options(merge({
failOnError: IF_NOT_DEV,
emitWarning: IF_NOT_DEV,
emitError: IF_NOT_DEV,
cwd: neutrino.options.root,
useEslintrc: false,
root: true,
plugins: ['babel'],
baseConfig: {},
envs: ['es6'],
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2017,
sourceType: 'module',
ecmaFeatures: {
objectLiteralDuplicateProperties: false,
generators: true,
impliedStrict: true
}
},
settings: {},
globals: ['process'],
rules: {}
}, options.eslint || {}));
if (options.include) {
rule.include.merge(options.include);
}
if (options.exclude) {
rule.exclude.merge(options.exclude);
}
neutrino.eslintrc = () => {
const options = clone(config.module.rule('lint').loaders.get('eslint').options);
const options = clone(config.module.rule('lint').use('eslint').get('options'));
options.extends = options.baseConfig.extends;
options.useEslintrc = true;

1
packages/neutrino-middleware-eslint/package.json

@ -18,6 +18,7 @@
"babel-eslint": "^7.1.1",
"deepmerge": "^1.3.2",
"eslint": "^3.16.1",
"eslint-config-airbnb-base": "^11.1.1",
"eslint-loader": "^1.6.3",
"eslint-plugin-babel": "^4.1.0",
"eslint-plugin-import": "^2.2.0",

4
packages/neutrino-middleware-eslint/yarn.lock

@ -324,6 +324,10 @@ escope@^3.6.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-config-airbnb-base@^11.1.1:
version "11.1.1"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.1.tgz#61e9e89e4eb89f474f6913ac817be9fbb59063e0"
eslint-import-resolver-node@^0.2.0:
version "0.2.3"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c"

11
packages/neutrino-middleware-font-loader/index.js

@ -8,15 +8,20 @@ module.exports = ({ config }, options) => {
config.module
.rule('woff')
.test(/\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/)
.loader('url', urlLoader, { limit, mimetype: 'application/font-woff' });
.use('url')
.loader(urlLoader)
.options({ limit, mimetype: 'application/font-woff' });
config.module
.rule('ttf')
.test(/\.ttf(\?v=\d+\.\d+\.\d+)?$/)
.loader('url', urlLoader, { limit, mimetype: 'application/octet-stream' });
.use('url')
.loader(urlLoader)
.options({ limit, mimetype: 'application/octet-stream' });
config.module
.rule('eot')
.test(/\.eot(\?v=\d+\.\d+\.\d+)?$/)
.loader('file', fileLoader);
.use('file')
.loader(fileLoader);
};

2
packages/neutrino-middleware-hot/index.js

@ -1,3 +1,3 @@
const { HotModuleReplacementPlugin } = require('webpack');
module.exports = ({ config }) => config.plugin('hot', HotModuleReplacementPlugin);
module.exports = ({ config }) => config.plugin('hot').use(HotModuleReplacementPlugin);

4
packages/neutrino-middleware-html-loader/index.js

@ -1,4 +1,6 @@
module.exports = ({ config }) => config.module
.rule('html')
.test(/\.html$/)
.loader('file', require.resolve('file-loader'), { name: '[name].[ext]' });
.use('file')
.loader(require.resolve('file-loader'))
.options({ name: '[name].[ext]' });

30
packages/neutrino-middleware-html-template/index.js

@ -2,16 +2,20 @@ const HtmlPlugin = require('html-webpack-plugin');
const template = require('html-webpack-template');
const merge = require('deepmerge');
module.exports = ({ config }, options) => config.plugin('html', HtmlPlugin, merge({
template,
inject: false,
appMountId: 'root',
xhtml: true,
mobile: true,
minify: {
useShortDoctype: true,
keepClosingSlash: true,
collapseWhitespace: true,
preserveLineBreaks: true,
}
}, options));
module.exports = ({ config }, options) => config
.plugin('html')
.use(HtmlPlugin, [
merge({
template,
inject: false,
appMountId: 'root',
xhtml: true,
mobile: true,
minify: {
useShortDoctype: true,
keepClosingSlash: true,
collapseWhitespace: true,
preserveLineBreaks: true,
}
}, options)
]);

3
packages/neutrino-middleware-html-template/package.json

@ -17,7 +17,8 @@
"dependencies": {
"deepmerge": "^1.3.2",
"html-webpack-plugin": "^2.28.0",
"html-webpack-template": "^6.0.1"
"html-webpack-template": "^6.0.1",
"webpack": "^2.2.1"
},
"peerDependencies": {
"neutrino": "^5.0.0"

1568
packages/neutrino-middleware-html-template/yarn.lock

File diff suppressed because it is too large

11
packages/neutrino-middleware-image-loader/index.js

@ -7,15 +7,20 @@ module.exports = ({ config }, options) => {
config.module
.rule('svg')
.test(/\.svg(\?v=\d+\.\d+\.\d+)?$/)
.loader('url', urlLoader, { limit, mimetype: 'application/svg+xml' });
.use('url')
.loader(urlLoader)
.options({ limit, mimetype: 'application/svg+xml' });
config.module
.rule('img')
.test(/\.(png|jpg|jpeg|gif)$/)
.loader('url', urlLoader, { limit });
.use('url')
.loader(urlLoader)
.options({ limit });
config.module
.rule('ico')
.test(/\.ico(\?v=\d+\.\d+\.\d+)?$/)
.loader('url', urlLoader);
.use('url')
.loader(urlLoader);
};

3
packages/neutrino-middleware-loader-merge/index.js

@ -2,4 +2,5 @@ const merge = require('deepmerge');
module.exports = (ruleId, loaderId) => ({ config }, options) => config.module
.rule(ruleId)
.loader(loaderId, _opts => merge(_opts, options));
.use(loaderId)
.tap(opts => merge(opts, options));

2
packages/neutrino-middleware-minify/index.js

@ -1,3 +1,3 @@
const BabiliPlugin = require('babili-webpack-plugin');
module.exports = ({ config }) => config.plugin('minify', BabiliPlugin);
module.exports = ({ config }) => config.plugin('minify').use(BabiliPlugin);

2
packages/neutrino-middleware-named-modules/index.js

@ -1,3 +1,3 @@
const { NamedModulesPlugin } = require('webpack');
module.exports = ({ config }) => config.plugin('named-modules', NamedModulesPlugin);
module.exports = ({ config }) => config.plugin('named-modules').use(NamedModulesPlugin);

2
packages/neutrino-middleware-progress/index.js

@ -1,3 +1,3 @@
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
module.exports = ({ config }) => config.plugin('progress', ProgressBarPlugin);
module.exports = ({ config }) => config.plugin('progress').use(ProgressBarPlugin);

3
packages/neutrino-middleware-progress/package.json

@ -15,7 +15,8 @@
"homepage": "https://neutrino.js.org",
"bugs": "https://github.com/mozilla-neutrino/neutrino-dev/issues",
"dependencies": {
"progress-bar-webpack-plugin": "^1.9.3"
"progress-bar-webpack-plugin": "^1.9.3",
"webpack": "^2.2.1"
},
"peerDependencies": {
"neutrino": "^5.0.0"

1687
packages/neutrino-middleware-progress/yarn.lock

File diff suppressed because it is too large

2
packages/neutrino-middleware-start-server/index.js

@ -1,3 +1,3 @@
const StartServerPlugin = require('start-server-webpack-plugin');
module.exports = ({ config }, options) => config.plugin('start-server', StartServerPlugin, options.name);
module.exports = ({ config }, options) => config.plugin('start-server').use(StartServerPlugin, [options.name]);

4
packages/neutrino-middleware-style-loader/index.js

@ -1,5 +1,5 @@
module.exports = ({ config }) => config.module
.rule('style')
.test(/\.css$/)
.loader('style', require.resolve('style-loader'))
.loader('css', require.resolve('css-loader'));
.use('style').loader(require.resolve('style-loader')).end()
.use('css').loader(require.resolve('css-loader'));

45
packages/neutrino-preset-airbnb-base/index.js

@ -1,28 +1,35 @@
const lint = require('neutrino-middleware-eslint');
const merge = require('deepmerge');
const { join } = require('path');
module.exports = (neutrino, options) => neutrino.use(lint, merge({
include: options.include ? [] : [join(process.cwd(), 'SRC')],
eslint: {
baseConfig: {
extends: ['airbnb-base']
},
rules: {
// handled by babel rules
'new-cap': 'off',
module.exports = (neutrino, options) => {
neutrino.use(lint, merge({
eslint: {
baseConfig: {
extends: ['airbnb-base']
},
rules: {
// handled by babel rules
'new-cap': 'off',
// handled by babel rules
'object-curly-spacing': 'off',
// handled by babel rules
'object-curly-spacing': 'off',
// require a capital letter for constructors
'babel/new-cap': ['error', { newIsCap: true }],
// require a capital letter for constructors
'babel/new-cap': ['error', { newIsCap: true }],
// require padding inside curly braces
'babel/object-curly-spacing': ['error', 'always'],
// require padding inside curly braces
'babel/object-curly-spacing': ['error', 'always'],
// guard against awaiting async functions inside of a loop
'babel/no-await-in-loop': 'error'
// guard against awaiting async functions inside of a loop
'babel/no-await-in-loop': 'error'
}
}
}, options));
if (!options.include && !options.exclude) {
neutrino.config.module
.rule('lint')
.include
.add(neutrino.options.source);
}
}, options));
};

57
packages/neutrino-preset-jest/src/index.js

@ -1,19 +1,18 @@
const { runCLI } = require('jest-cli');
const fs = require('fs');
const path = require('path');
const { writeFileSync } = require('fs');
const { join } = require('path');
const merge = require('deepmerge');
const os = require('os');
const { tmpdir } = require('os');
const clone = require('lodash.clonedeep');
const loaderMerge = require('neutrino-middleware-loader-merge');
const pkg = require(path.join(process.cwd(), 'package.json'));
function normalizeJestOptions(jestOptions, config, args) {
const options = clone(jestOptions);
const aliases = config.options.get('alias') || {};
const aliases = config.resolve.alias.entries() || {};
Object
.keys(aliases)
.map(key => options.moduleNameMapper[key] = path.join('<rootDir>', aliases[key]));
.map(key => options.moduleNameMapper[key] = join('<rootDir>', aliases[key]));
options.moduleFileExtensions = [...new Set([
...options.moduleFileExtensions,
@ -24,7 +23,7 @@ function normalizeJestOptions(jestOptions, config, args) {
...config.resolve.modules.values()
])];
options.globals = Object.assign({
BABEL_OPTIONS: config.module.rule('compile').loaders.get('babel').options
BABEL_OPTIONS: config.module.rule('compile').use('babel').get('options')
}, options.globals);
if (args.files.length) {
@ -35,24 +34,20 @@ function normalizeJestOptions(jestOptions, config, args) {
}
module.exports = neutrino => {
const jestOptions = merge.all([
{
bail: true,
transform: {
"\\.(js|jsx)$": require.resolve('./transformer')
},
roots: [path.join(process.cwd(), 'test')],
testRegex: '(_test|_spec|\\.test|\\.spec)\\.jsx?$',
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: [path.join(__dirname, '../node_modules')],
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': require.resolve('./file-mock'),
'\\.(css|less|sass)$': require.resolve('./style-mock')
}
const jestOptions = merge({
bail: true,
transform: {
"\\.(js|jsx)$": require.resolve('./transformer')
},
pkg.jest || {},
neutrino.options.jest || {}
]);
roots: [neutrino.options.tests],
testRegex: '(_test|_spec|\\.test|\\.spec)\\.jsx?$',
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: [join(__dirname, '../node_modules')],
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': require.resolve('./file-mock'),
'\\.(css|less|sass)$': require.resolve('./style-mock')
}
}, neutrino.options.jest || {});
neutrino.use(loaderMerge('compile', 'babel'), {
env: {
@ -73,20 +68,14 @@ module.exports = neutrino => {
neutrino.on('test', args => {
const options = normalizeJestOptions(jestOptions, neutrino.config, args);
const configFile = path.join(os.tmpdir(), 'config.json');
const configFile = join(tmpdir(), 'config.json');
return new Promise((resolve, reject) => {
const cliOptions = { config: configFile, coverage: args.coverage, watch: args.watch };
const dir = options.rootDir || process.cwd();
const dir = options.rootDir || neutrino.options.root;
fs.writeFileSync(configFile, `${JSON.stringify(options, null, 2)}\n`);
runCLI(cliOptions, dir, result => {
if (result.numFailedTests || result.numFailedTestSuites) {
reject();
} else {
resolve();
}
});
writeFileSync(configFile, `${JSON.stringify(options, null, 2)}\n`);
runCLI(cliOptions, dir, result => result.numFailedTests || result.numFailedTestSuites ? reject() : resolve());
});
});
};

16
packages/neutrino-preset-karma/index.js

@ -1,7 +1,11 @@
const { Server } = require('karma');
const merge = require('deepmerge');
const { join } = require('path');
module.exports = neutrino => {
const tests = join(neutrino.options.tests, '**/*_test.js');
const sources = join(neutrino.options.source, '**/*.js');
const defaults = {
plugins: [
require.resolve('karma-webpack'),
@ -10,7 +14,7 @@ module.exports = neutrino => {
require.resolve('karma-mocha'),
require.resolve('karma-mocha-reporter')
],
basePath: process.cwd(),
basePath: neutrino.options.root,
browsers: [process.env.CI ? 'ChromeCI' : 'Chrome'],
customLaunchers: {
ChromeCI: {
@ -19,10 +23,10 @@ module.exports = neutrino => {
}
},
frameworks: ['mocha'],
files: ['test/**/*_test.js'],
files: [tests],
preprocessors: {
'test/**/*_test.js': ['webpack'],
'src/**/*.js': ['webpack']
[tests]: ['webpack'],
[sources]: ['webpack']
},
webpackMiddleware: { noInfo: true },
reporters: ['mocha', 'coverage'],
@ -52,8 +56,6 @@ module.exports = neutrino => {
karma.files = files;
}
return new Promise(resolve => {
new Server(karma, resolve).start();
});
return new Promise(resolve => new Server(karma, resolve).start());
});
};

2
packages/neutrino-preset-mocha/src/index.js

@ -13,7 +13,7 @@ module.exports = neutrino => {
neutrino.on('test', ({ files }) => mocha(
merge({ reporter: 'spec', ui: 'tdd', bail: true }, neutrino.options.mocha || {}),
neutrino.config.module.rule('compile').loaders.get('babel').options,
neutrino.config.module.rule('compile').use('babel').get('options'),
files
));
};

33
packages/neutrino-preset-node/index.js

@ -10,20 +10,19 @@ const namedModules = require('neutrino-middleware-named-modules');
const nodeExternals = require('webpack-node-externals');
const { join } = require('path');
const CWD = process.cwd();
const SRC = join(CWD, 'src');
const BUILD = join(CWD, 'build');
const TEST = join(CWD, 'test');
const PROJECT_MODULES = join(CWD, 'node_modules');
const MODULES = join(__dirname, 'node_modules');
const PKG = require(join(CWD, 'package.json'));
module.exports = neutrino => {
const { config } = neutrino;
let pkg = {};
try {
pkg = require(join(neutrino.options.root, 'package.json'));
} catch (ex) {}
neutrino.use(namedModules);
neutrino.use(compile, {
include: [SRC, TEST],
include: [neutrino.options.source, neutrino.options.tests],
babel: {
plugins: [require.resolve('babel-plugin-dynamic-import-node')],
presets: [
@ -46,19 +45,19 @@ module.exports = neutrino => {
.end()
.devtool('source-map')
.externals([nodeExternals({ whitelist: [/^webpack/] })])
.context(CWD)
.context(neutrino.options.root)
.entry('index')
.add(join(SRC, 'index.js'))
.add(neutrino.options.entry)
.end()
.output
.path(BUILD)
.path(neutrino.options.output)
.filename('[name].js')
.libraryTarget('commonjs2')
.chunkFilename('[id].[hash:5]-[chunkhash:7].js')
.end()
.resolve
.modules
.add(PROJECT_MODULES)
.add(neutrino.options.node_modules)
.add(MODULES)
.end()
.extensions
@ -68,21 +67,21 @@ module.exports = neutrino => {
.end()
.resolveLoader
.modules
.add(PROJECT_MODULES)
.add(neutrino.options.node_modules)
.add(MODULES);
const hasSourceMap = (PKG.dependencies && 'source-map-support' in PKG.dependencies) ||
(PKG.devDependencies && 'source-map-support' in PKG.devDependencies);
const hasSourceMap = (pkg.dependencies && 'source-map-support' in pkg.dependencies) ||
(pkg.devDependencies && 'source-map-support' in pkg.devDependencies);
if (hasSourceMap) {
neutrino.use(banner);
}
if (process.env.NODE_ENV !== 'development') {
neutrino.use(clean, { paths: [BUILD] });
neutrino.use(clean, { paths: [neutrino.options.output] });
neutrino.use(progress);
neutrino.use(copy, {
patterns: [{ context: SRC, from: `**/*` }],
patterns: [{ context: neutrino.options.source, from: `**/*` }],
options: { ignore: ['*.js*'] }
});
} else {
@ -90,7 +89,7 @@ module.exports = neutrino => {
config.entry('index').add('webpack/hot/poll?1000');
config.output.devtoolModuleFilenameTemplate('[absolute-resource-path]');
neutrino.use(hot);
neutrino.use(startServer, join(SRC, 'index.js'));
neutrino.use(startServer, neutrino.options.entry);
}
if (config.module.rules.has('lint')) {

23
packages/neutrino-preset-node/test/web_test.js

@ -0,0 +1,23 @@
import test from 'ava';
import { validate } from 'webpack';
import Neutrino from 'neutrino';
test('loads preset', t => {
t.notThrows(() => require('..'));
});
test('uses preset', t => {
const api = new Neutrino();
t.notThrows(() => api.use(require('..')));
});
test('valid preset', t => {
const api = new Neutrino();
api.use(require('..'));
const errors = validate(api.getWebpackOptions());
t.is(errors.length, 0);
});

12
packages/neutrino-preset-react/index.js

@ -21,13 +21,11 @@ module.exports = neutrino => {
config.resolve.modules.add(MODULES);
config.resolve.extensions.add('.jsx');
config.resolveLoader.modules.add(MODULES);
config
.externals({
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': 'window'
});
config.externals({
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': 'window'
});
if (process.env.NODE_ENV === 'development') {
config

23
packages/neutrino-preset-react/test/web_test.js

@ -0,0 +1,23 @@
import test from 'ava';
import { validate } from 'webpack';
import Neutrino from 'neutrino';
test('loads preset', t => {
t.notThrows(() => require('..'));
});
test('uses preset', t => {
const api = new Neutrino();
t.notThrows(() => api.use(require('..')));
});
test('valid preset', t => {
const api = new Neutrino();
api.use(require('..'));
const errors = validate(api.getWebpackOptions());
t.is(errors.length, 0);
});

30
packages/neutrino-preset-web/index.js

@ -16,12 +16,6 @@ const namedModules = require('neutrino-middleware-named-modules');
const { join } = require('path');
const { pathOr } = require('ramda');
const CWD = process.cwd();
const SRC = join(CWD, 'src');
const BUILD = join(CWD, 'build');
const TEST = join(CWD, 'test');
const PKG = require(join(CWD, 'package.json'));
const PROJECT_MODULES = join(CWD, 'node_modules');
const MODULES = join(__dirname, 'node_modules');
module.exports = neutrino => {
@ -35,7 +29,7 @@ module.exports = neutrino => {
neutrino.use(htmlTemplate);
neutrino.use(namedModules);
neutrino.use(compileLoader, {
include: [SRC, TEST],
include: [neutrino.options.source, neutrino.options.tests],
babel: {
plugins: [require.resolve('babel-plugin-syntax-dynamic-import')],
presets: [
@ -64,20 +58,20 @@ module.exports = neutrino => {
config
.target('web')
.context(CWD)
.context(neutrino.options.root)
.entry('index')
.add(require.resolve('babel-polyfill'))
.add(join(SRC, 'index.js'));
.add(neutrino.options.entry);
config.output
.path(BUILD)
.path(neutrino.options.output)
.publicPath('./')
.filename('[name].bundle.js')
.chunkFilename('[id].[chunkhash].js');
config.resolve.modules.add(PROJECT_MODULES).add(MODULES);
config.resolve.modules.add(neutrino.options.node_modules).add(MODULES);
config.resolve.extensions.add('.js').add('.json');
config.resolveLoader.modules.add(PROJECT_MODULES).add(MODULES);
config.resolveLoader.modules.add(neutrino.options.node_modules).add(MODULES);
config.node
.set('console', false)
@ -99,15 +93,15 @@ module.exports = neutrino => {
if (process.env.NODE_ENV === 'development') {
const protocol = !!process.env.HTTPS ? 'https' : 'http';
const host = process.env.HOST || pathOr('localhost', ['neutrino', 'config', 'devServer', 'host'], PKG);
const port = process.env.PORT || pathOr(5000, ['neutrino', 'config', 'devServer', 'port'], PKG);
const host = process.env.HOST || pathOr('localhost', ['options', 'config', 'devServer', 'host'], neutrino);
const port = process.env.PORT || pathOr(5000, ['options', 'config', 'devServer', 'port'], neutrino);
neutrino.use(hot);
neutrino.use(devServer, {
host,
port,
https: protocol === 'https',
contentBase: SRC
https: pathOr(protocol === 'https', ['options', 'config', 'devServer', 'https'], neutrino),
contentBase: neutrino.options.source
});
config
@ -116,11 +110,11 @@ module.exports = neutrino => {
.add(`webpack-dev-server/client?${protocol}://${host}:${port}/`)
.add('webpack/hot/dev-server');
} else {
neutrino.use(clean, { paths: [BUILD] });
neutrino.use(clean, { paths: [neutrino.options.output] });
neutrino.use(progress);
neutrino.use(minify);
neutrino.use(copy, {
patterns: [{ context: SRC, from: `**/*` }],
patterns: [{ context: neutrino.options.source, from: `**/*` }],
options: { ignore: ['*.js*'] }
});
config.output.filename('[name].[chunkhash].bundle.js');

23
packages/neutrino-preset-web/test/web_test.js

@ -0,0 +1,23 @@
import test from 'ava';
import { validate } from 'webpack';
import Neutrino from 'neutrino';
test('loads preset', t => {
t.notThrows(() => require('..'));
});
test('uses preset', t => {
const api = new Neutrino();
t.notThrows(() => api.use(require('..')));
});
test('valid preset', t => {
const api = new Neutrino();
api.use(require('..'));
const errors = validate(api.getWebpackOptions());
t.is(errors.length, 0);
});

8
packages/neutrino/bin/neutrino

@ -59,8 +59,8 @@ function run(command, presets) {
process.env.NODE_ENV = environments[command];
const options = pathOr({}, ['neutrino', 'options'], pkg);
const api = new Neutrino(options);
const cwd = process.cwd();
const config = pathOr({}, ['neutrino', 'config'], pkg);
const api = new Neutrino(Object.assign(options, { config }));
// Grab all presets and merge them into a single webpack-chain config instance
presets.forEach(preset => {
@ -89,8 +89,8 @@ function run(command, presets) {
});
// Also grab any Neutrino config from package.json and merge it into the config at a higher precedence
if (pkg.neutrino && pkg.neutrino.config) {
api.config.merge(pkg.neutrino.config);
if (Object.keys(config).length) {
api.config.merge(config);
}
if (args.inspect) {

3
packages/neutrino/package.json

@ -23,11 +23,12 @@
},
"dependencies": {
"deep-sort-object": "^1.0.1",
"deepmerge": "^1.3.2",
"javascript-stringify": "^1.6.0",
"ora": "^1.1.0",
"ramda": "^0.23.0",
"webpack": "^2.2.1",
"webpack-chain": "^2.0.0",
"webpack-chain": "^3.0.0",
"webpack-dev-server": "^2.4.1",
"yargs": "^6.6.0"
}

17
packages/neutrino/src/neutrino.js

@ -1,15 +1,24 @@
const path = require('path');
const EventEmitter = require('events').EventEmitter;
const { join } = require('path');
const { EventEmitter } = require('events');
const DevServer = require('webpack-dev-server');
const webpack = require('webpack');
const Config = require('webpack-chain');
const ora = require('ora');
const merge = require('deepmerge');
class Neutrino extends EventEmitter {
constructor(options) {
constructor(options = {}) {
super();
const root = options.root || process.cwd();
const source = options.source || join(root, 'src');
const output = options.output || join(root, 'build');
const tests = options.tests || join(root, 'test');
const node_modules = options.node_modules || join(root, 'node_modules');
const entry = options.entry || join(source, 'index.js');
this.config = new Config();
this.options = options;
this.options = merge(options, { root, source, output, tests, node_modules, entry });
}
use(preset, options = {}) {

12
packages/neutrino/test/api_test.js

@ -13,7 +13,9 @@ test('initialization stores options', t => {
const options = { alpha: 'a', beta: 'b', gamma: 'c' };
const api = new Neutrino(options);
t.deepEqual(options, api.options);
t.is(api.options.alpha, options.alpha);
t.is(api.options.beta, options.beta);
t.is(api.options.gamma, options.gamma);
});
test('creates an instance of webpack-chain', t => {
@ -91,8 +93,12 @@ test('creates a Webpack config', t => {
api.config.module
.rule('compile')
.test(/\.js$/)
.include('src')
.loader('babel', 'babel-loader', { alpha: 'a', beta: 'b' });
.include
.add('src')
.end()
.use('babel')
.loader('babel-loader')
.options({ alpha: 'a', beta: 'b' });
});
t.deepEqual(api.getWebpackOptions(), {

6
packages/neutrino/yarn.lock

@ -2157,9 +2157,9 @@ wbuf@^1.1.0, wbuf@^1.4.0:
dependencies:
minimalistic-assert "^1.0.0"
webpack-chain@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-2.0.0.tgz#ddf52623b110e552684cec7e85f97b24a7b57f10"
webpack-chain@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-3.0.0.tgz#20d0b92e84cb294035e1fa03ce2fb8805cce51b6"
dependencies:
deepmerge "^1.3.2"

718
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save