refactor: build
This commit is contained in:
parent
668304408d
commit
9f08899cb5
|
@ -4,19 +4,20 @@ const {join} = require('path');
|
|||
const airbnb = require('@neutrinojs/airbnb');
|
||||
const banner = require('@neutrinojs/banner');
|
||||
const copy = require('@neutrinojs/copy');
|
||||
const node = require('@neutrinojs/node');
|
||||
const glob = require('glob');
|
||||
|
||||
const fleck = require('../src/bootstrap/fleck');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
module.exports = require('../src/bootstrap/fleck.neutrinorc');
|
||||
const config = require('../src/bootstrap/fleck.neutrinorc');
|
||||
|
||||
// Dotfiles.
|
||||
module.exports.use.push((neutrino) => {
|
||||
config.use.push(({config}) => {
|
||||
['eslintrc', 'eslint.defaults'].forEach((filename) => {
|
||||
neutrino.config
|
||||
config
|
||||
.entry(`server/build/.${filename}`)
|
||||
.clear()
|
||||
.add(`./src/server/build/${filename}`);
|
||||
|
@ -24,23 +25,19 @@ module.exports.use.push((neutrino) => {
|
|||
});
|
||||
|
||||
// Tests.
|
||||
module.exports.use.push((neutrino) => {
|
||||
config.use.push(({config}) => {
|
||||
// Test entrypoint.
|
||||
const testPaths = glob.sync(join(FLECKS_CORE_ROOT, 'test/*.js'));
|
||||
testPaths.push(...glob.sync(join(FLECKS_CORE_ROOT, `test/platforms/server/*.js`)));
|
||||
if (testPaths.length > 0) {
|
||||
const testEntry = neutrino.config.entry('test').clear();
|
||||
const testEntry = config.entry('test').clear();
|
||||
testPaths.forEach((path) => testEntry.add(path));
|
||||
}
|
||||
});
|
||||
|
||||
module.exports.use.unshift((neutrino) => {
|
||||
neutrino.config.plugins.delete('start-server');
|
||||
});
|
||||
config.use.unshift(fleck());
|
||||
|
||||
module.exports.use.unshift(node({clean: {cleanStaleWebpackAssets: false}}));
|
||||
|
||||
module.exports.use.unshift(
|
||||
config.use.unshift(
|
||||
airbnb({
|
||||
eslint: {
|
||||
baseConfig: {
|
||||
|
@ -53,14 +50,14 @@ module.exports.use.unshift(
|
|||
}),
|
||||
);
|
||||
|
||||
module.exports.use.push(banner({
|
||||
config.use.push(banner({
|
||||
banner: '#!/usr/bin/env node',
|
||||
include: /^cli\.js$/,
|
||||
pluginId: 'shebang',
|
||||
raw: true,
|
||||
}))
|
||||
|
||||
module.exports.use.push(({config}) => {
|
||||
config.use.push(({config}) => {
|
||||
config
|
||||
.plugin('executable')
|
||||
.use(class Executable {
|
||||
|
@ -76,3 +73,5 @@ module.exports.use.push(({config}) => {
|
|||
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
@ -54,9 +54,10 @@
|
|||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/register": "^7.12.10",
|
||||
"@neutrinojs/airbnb": "^9.4.0",
|
||||
"@neutrinojs/banner": "^9.4.0",
|
||||
"@neutrinojs/clean": "^9.5.0",
|
||||
"@neutrinojs/compile-loader": "^9.5.0",
|
||||
"@neutrinojs/copy": "^9.4.0",
|
||||
"@neutrinojs/node": "^9.1.0",
|
||||
"babel-merge": "^3.0.0",
|
||||
"babel-plugin-prepend": "^1.0.2",
|
||||
"chai": "4.2.0",
|
||||
|
@ -80,7 +81,6 @@
|
|||
"webpack-node-externals": "2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@neutrinojs/banner": "^9.4.0",
|
||||
"glob": "^7.2.0",
|
||||
"mocha": "^8.3.2"
|
||||
}
|
||||
|
|
|
@ -30,19 +30,19 @@ const resolver = (source) => (path) => {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = () => (neutrino) => {
|
||||
const {packageJson: {name, files = []}, source} = neutrino.options;
|
||||
module.exports = () => ({config, options}) => {
|
||||
const {packageJson: {name, files = []}, source} = options;
|
||||
// index is not taken for granted.
|
||||
neutrino.config.entryPoints.delete('index');
|
||||
config.entryPoints.delete('index');
|
||||
// Alias this package.
|
||||
neutrino.config.resolve.alias
|
||||
config.resolve.alias
|
||||
.set(name, join(FLECKS_CORE_ROOT, 'src'));
|
||||
// Calculate entry points from `files`.
|
||||
files
|
||||
.filter(resolver(source))
|
||||
.forEach((file) => {
|
||||
const trimmed = join(dirname(file), basename(file, extname(file)));
|
||||
neutrino.config
|
||||
config
|
||||
.entry(trimmed)
|
||||
.clear()
|
||||
.add(`./src/${trimmed}`);
|
||||
|
|
|
@ -1,11 +1,63 @@
|
|||
const banner = require('@neutrinojs/banner');
|
||||
const clean = require('@neutrinojs/clean');
|
||||
const compileLoader = require('@neutrinojs/compile-loader');
|
||||
const babelMerge = require('babel-merge');
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
|
||||
module.exports = () => (neutrino) => {
|
||||
const {name} = neutrino.options.packageJson;
|
||||
const R = require('./require');
|
||||
|
||||
module.exports = ({
|
||||
babel = {},
|
||||
targets = {
|
||||
esmodules: true,
|
||||
node: 'current',
|
||||
},
|
||||
} = {}) => (neutrino) => {
|
||||
const {config, options} = neutrino;
|
||||
const {name} = options.packageJson;
|
||||
neutrino.use(
|
||||
compileLoader({
|
||||
include: [options.source, options.tests],
|
||||
babel: babelMerge(
|
||||
{
|
||||
plugins: [R.resolve('@babel/plugin-syntax-dynamic-import')],
|
||||
presets: [
|
||||
[
|
||||
R.resolve('@babel/preset-env'),
|
||||
{
|
||||
shippedProposals: true,
|
||||
targets,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
babel,
|
||||
),
|
||||
}),
|
||||
);
|
||||
neutrino.use(banner());
|
||||
neutrino.use(clean({cleanStaleWebpackAssets: false}));
|
||||
/* eslint-disable indent */
|
||||
neutrino.config
|
||||
config
|
||||
.context(options.root)
|
||||
.devtool('source-map')
|
||||
.externals(nodeExternals({importType: 'umd'}))
|
||||
.target('node')
|
||||
.resolve
|
||||
.extensions
|
||||
.merge([
|
||||
'.wasm',
|
||||
...options.extensions.map((ext) => `.${ext}`),
|
||||
'.json',
|
||||
])
|
||||
.end()
|
||||
.end()
|
||||
.stats({
|
||||
children: false,
|
||||
colors: true,
|
||||
entrypoints: false,
|
||||
modules: false,
|
||||
})
|
||||
.optimization
|
||||
.splitChunks(false)
|
||||
.runtimeChunk(false)
|
||||
|
@ -14,16 +66,11 @@ module.exports = () => (neutrino) => {
|
|||
.filename('[name].js')
|
||||
.library(name)
|
||||
.libraryTarget('umd')
|
||||
.path(options.output)
|
||||
.umdNamedDefine(true)
|
||||
.end()
|
||||
.node
|
||||
.set('__dirname', false)
|
||||
.set('__filename', false);
|
||||
/* eslint-enable indent */
|
||||
const options = neutrino.config.module
|
||||
.rule('compile')
|
||||
.use('babel')
|
||||
.get('options');
|
||||
options.presets[0][1].targets = {esmodules: true};
|
||||
neutrino.config.externals(nodeExternals({importType: 'umd'}));
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const copy = require('@neutrinojs/copy');
|
||||
|
||||
const autoentry = require('./autoentry');
|
||||
const fleck = require('./fleck');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
|
@ -32,6 +31,5 @@ module.exports = {
|
|||
pluginId: '@flecks/core.copy',
|
||||
}),
|
||||
autoentry(),
|
||||
fleck(),
|
||||
],
|
||||
};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import {Hooks} from './flecks';
|
||||
|
||||
export {default as autoentry} from './bootstrap/autoentry';
|
||||
export {default as fleck} from './bootstrap/fleck';
|
||||
export {default as compose} from './compose';
|
||||
export {default as D} from './debug';
|
||||
export {default as ensureUniqueReduction} from './ensure-unique-reduction';
|
||||
|
|
|
@ -101,7 +101,6 @@ export default (program, flecks) => {
|
|||
['-d, --no-production', 'dev build'],
|
||||
['-h, --hot', 'build with hot module reloading'],
|
||||
['-w, --watch', 'watch for changes'],
|
||||
['-v, --verbose', 'verbose output'],
|
||||
],
|
||||
description: 'build',
|
||||
action: (target, opts) => {
|
||||
|
@ -109,7 +108,6 @@ export default (program, flecks) => {
|
|||
hot,
|
||||
production,
|
||||
watch,
|
||||
verbose,
|
||||
} = opts;
|
||||
debug('Building...', opts);
|
||||
const webpackConfig = flecks.buildConfig('webpack.config.js');
|
||||
|
@ -118,7 +116,6 @@ export default (program, flecks) => {
|
|||
'--colors',
|
||||
'--config', webpackConfig,
|
||||
'--mode', (production && !hot) ? 'production' : 'development',
|
||||
...(verbose ? ['--stats', 'verbose'] : []),
|
||||
...((watch || hot) ? ['--watch'] : []),
|
||||
];
|
||||
return spawnWith(
|
||||
|
|
|
@ -14,6 +14,7 @@ export {
|
|||
targetNeutrinos,
|
||||
} from './commands';
|
||||
export {default as Flecks} from './flecks';
|
||||
export {default as fleck} from '../bootstrap/fleck';
|
||||
export {default as require} from '../bootstrap/require';
|
||||
export {JsonStream, transform} from './stream';
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@flecks/core": "^1.3.0",
|
||||
"@neutrinojs/node": "^9.4.0",
|
||||
"babel-merge": "^3.0.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"debug": "^4.3.3",
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
const {join} = require('path');
|
||||
|
||||
const {D} = require('@flecks/core');
|
||||
const {Flecks} = require('@flecks/core/server');
|
||||
const node = require('@neutrinojs/node');
|
||||
const {fleck, Flecks} = require('@flecks/core/server');
|
||||
const babelmerge = require('babel-merge');
|
||||
const glob = require('glob');
|
||||
|
||||
|
@ -19,44 +18,28 @@ module.exports = (async () => {
|
|||
const flecks = Flecks.bootstrap();
|
||||
debug('bootstrapped');
|
||||
|
||||
const compiler = flecks.invokeFleck(
|
||||
'@flecks/fleck.compiler',
|
||||
flecks.get('@flecks/fleck.compiler'),
|
||||
);
|
||||
if (compiler) {
|
||||
config.use.unshift(compiler);
|
||||
}
|
||||
else {
|
||||
config.use.unshift((neutrino) => {
|
||||
neutrino.config.plugins.delete('start-server');
|
||||
});
|
||||
const configFile = flecks.buildConfig('babel.config.js');
|
||||
config.use.unshift(node({
|
||||
babel: {configFile},
|
||||
clean: {
|
||||
cleanStaleWebpackAssets: false,
|
||||
},
|
||||
}));
|
||||
}
|
||||
// Compile.
|
||||
const rcBabel = flecks.babel();
|
||||
debug('.flecksrc: babel: %O', rcBabel);
|
||||
config.use.push(fleck({
|
||||
babel: babelmerge(
|
||||
{configFile: flecks.buildConfig('babel.config.js')},
|
||||
...rcBabel.map(([, babel]) => babel),
|
||||
),
|
||||
}));
|
||||
|
||||
// Augment the compiler with babel config from flecksrc.
|
||||
config.use.push((neutrino) => {
|
||||
const rcBabel = flecks.babel();
|
||||
debug('.flecksrc: babel: %O', rcBabel);
|
||||
neutrino.config.module
|
||||
.rule('compile')
|
||||
.use('babel')
|
||||
.tap((options) => babelmerge(options, ...rcBabel.map(([, babel]) => babel)));
|
||||
config.use.push(({config}) => {
|
||||
config.stats(flecks.get('@flecks/flecks/server.stats'));
|
||||
});
|
||||
|
||||
config.use.push((neutrino) => {
|
||||
config.use.push(({config}) => {
|
||||
// Test entrypoint.
|
||||
const testPaths = glob.sync(join(FLECKS_CORE_ROOT, 'test/*.js'));
|
||||
for (let i = 0; i < flecks.platforms.length; ++i) {
|
||||
testPaths.push(...glob.sync(join(FLECKS_CORE_ROOT, `test/platforms/${flecks.platforms[i]}/*.js`)));
|
||||
}
|
||||
if (testPaths.length > 0) {
|
||||
const testEntry = neutrino.config.entry('test').clear();
|
||||
const testEntry = config.entry('test').clear();
|
||||
testPaths.forEach((path) => testEntry.add(path));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,6 +5,16 @@ import commands from './commands';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.commands': commands,
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Webpack stats configuration when building fleck target.
|
||||
*/
|
||||
stats: {
|
||||
chunks: false,
|
||||
colors: true,
|
||||
modules: false,
|
||||
},
|
||||
}),
|
||||
'@flecks/core.targets': () => ['fleck'],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,12 +30,6 @@ export default {
|
|||
},
|
||||
},
|
||||
],
|
||||
/**
|
||||
* Define neutrino compilation middleware (e.g. @neutrinojs/react).
|
||||
*/
|
||||
'@flecks/http/server.compiler': () => {
|
||||
return require('@neutrinojs/node');
|
||||
},
|
||||
/**
|
||||
* Define middleware to run when a route is matched.
|
||||
*/
|
||||
|
@ -66,4 +60,3 @@ export default {
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const copy = require('@neutrinojs/copy');
|
||||
const styleLoader = require('@neutrinojs/style-loader');
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
|
||||
module.exports = (async () => {
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies, global-require
|
||||
const config = await require('@flecks/fleck/server/build/fleck.neutrinorc');
|
||||
config.use.push(({config}) => {
|
||||
config.entryPoints.delete('server/build/template');
|
||||
config.externals(nodeExternals({
|
||||
allowlist: ['mocha/mocha.css'],
|
||||
importType: 'umd',
|
||||
}));
|
||||
});
|
||||
config.use.push(styleLoader({
|
||||
extract: {
|
||||
enabled: false,
|
||||
},
|
||||
style: {
|
||||
injectType: 'lazyStyleTag',
|
||||
},
|
||||
}));
|
||||
config.use.push(
|
||||
copy({
|
||||
copyUnmodified: true,
|
||||
|
|
|
@ -38,7 +38,12 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@flecks/core": "^1.3.0",
|
||||
"@neutrinojs/web": "^9.1.0",
|
||||
"@neutrinojs/dev-server": "^9.5.0",
|
||||
"@neutrinojs/font-loader": "^9.5.0",
|
||||
"@neutrinojs/html-loader": "^9.5.0",
|
||||
"@neutrinojs/html-template": "^9.5.0",
|
||||
"@neutrinojs/image-loader": "^9.5.0",
|
||||
"@neutrinojs/style-loader": "^9.5.0",
|
||||
"compression": "^1.7.4",
|
||||
"express": "^4.17.1",
|
||||
"glob": "^7.2.0",
|
||||
|
@ -50,7 +55,8 @@
|
|||
"react-dev-utils": "12.0.0",
|
||||
"source-map-loader": "^1.1.3",
|
||||
"webpack": "^4",
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-node-externals": "2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flecks/fleck": "^1.3.0",
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const devServer = require('@neutrinojs/dev-server');
|
||||
|
||||
module.exports = (flecks) => (neutrino) => {
|
||||
if ('production' === neutrino.config.get('mode')) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
devHost,
|
||||
devPort,
|
||||
|
@ -9,10 +8,11 @@ module.exports = (flecks) => (neutrino) => {
|
|||
devStats,
|
||||
port,
|
||||
} = flecks.get('@flecks/http/server');
|
||||
neutrino.config.devServer
|
||||
.hot(false)
|
||||
.host(devHost)
|
||||
.port(devPort || (port + 1))
|
||||
.public(devPublic)
|
||||
.stats(devStats);
|
||||
neutrino.use(devServer({
|
||||
hot: false,
|
||||
host: devHost,
|
||||
port: devPort || (port + 1),
|
||||
public: devPublic,
|
||||
stats: devStats,
|
||||
}));
|
||||
};
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
const {dirname, join} = require('path');
|
||||
const {realpath} = require('fs/promises');
|
||||
|
||||
const {D} = require('@flecks/core');
|
||||
const {Flecks} = require('@flecks/core/server');
|
||||
const web = require('@neutrinojs/web');
|
||||
const {Flecks, require: R} = require('@flecks/core/server');
|
||||
const htmlLoader = require('@neutrinojs/html-loader');
|
||||
const htmlTemplate = require('@neutrinojs/html-template');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
const {EnvironmentPlugin} = require('webpack');
|
||||
|
||||
const devServer = require('./dev-server');
|
||||
const outputs = require('./outputs');
|
||||
const runtime = require('./runtime');
|
||||
const targets = require('./targets');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
|
@ -18,6 +22,96 @@ module.exports = (async () => {
|
|||
debug('bootstrapping flecks...');
|
||||
const flecks = Flecks.bootstrap();
|
||||
debug('bootstrapped');
|
||||
// Build configuration.
|
||||
const build = async () => {
|
||||
const root = await realpath(
|
||||
dirname(R.resolve(join(flecks.resolve('@flecks/http'), 'entry.js'))),
|
||||
);
|
||||
return (neutrino) => {
|
||||
const {config, options} = neutrino;
|
||||
const isProduction = 'production' === config.get('mode');
|
||||
// Environment.
|
||||
config
|
||||
.plugin('environment')
|
||||
.use(EnvironmentPlugin, [{
|
||||
FLECKS_CORE_BUILD_TARGET: 'client',
|
||||
}]);
|
||||
// Entrypoints.
|
||||
const {output: originalOutput} = options;
|
||||
options.root = root;
|
||||
config.context(options.root);
|
||||
options.source = '.';
|
||||
options.mains.index = 'entry';
|
||||
options.mains.tests = {
|
||||
entry: './client/tests',
|
||||
title: 'Testbed',
|
||||
};
|
||||
options.output = join(originalOutput, flecks.get('@flecks/http/server.output'));
|
||||
neutrino.use(htmlLoader());
|
||||
Object.entries(options.mains).forEach(([name, mainsConfig]) => {
|
||||
const {entry, ...htmlTemplateConfig} = mainsConfig;
|
||||
config.entry(name).add(entry);
|
||||
neutrino.use(
|
||||
htmlTemplate({
|
||||
pluginId: `html-${name}`,
|
||||
filename: `${name}.html`,
|
||||
chunks: [name],
|
||||
inject: false,
|
||||
template: flecks.buildConfig('template.ejs'),
|
||||
...htmlTemplateConfig,
|
||||
}),
|
||||
);
|
||||
});
|
||||
// Fold in existing source maps.
|
||||
config.module
|
||||
.rule('maps')
|
||||
.test(/\.js$/)
|
||||
.enforce('pre')
|
||||
.use('source-map-loader')
|
||||
.loader('source-map-loader');
|
||||
// Optimization.
|
||||
config.optimization
|
||||
.minimize(isProduction)
|
||||
.splitChunks({
|
||||
chunks: 'all',
|
||||
name: !isProduction,
|
||||
})
|
||||
.runtimeChunk('single');
|
||||
// Outputs.
|
||||
config.output
|
||||
.chunkFilename(isProduction ? 'assets/[name].[contenthash:8].js' : 'assets/[name].js')
|
||||
.path(options.output)
|
||||
.publicPath('/')
|
||||
.filename(isProduction ? 'assets/[name].[contenthash:8].js' : 'assets/[name].js');
|
||||
config
|
||||
.devtool(isProduction ? 'source-map' : 'eval-source-map')
|
||||
.target('web');
|
||||
config.node
|
||||
.set('Buffer', true)
|
||||
.set('fs', 'empty')
|
||||
.set('tls', 'empty')
|
||||
.set('__dirname', false)
|
||||
.set('__filename', false);
|
||||
// Resolution.
|
||||
config.resolve.extensions
|
||||
.merge([
|
||||
'.wasm',
|
||||
...options.extensions.map((ext) => `.${ext}`),
|
||||
'.json',
|
||||
]);
|
||||
config.resolve.modules
|
||||
.merge([
|
||||
join(FLECKS_CORE_ROOT, 'node_modules'),
|
||||
'node_modules',
|
||||
]);
|
||||
// Reporting.
|
||||
config.stats(flecks.get('@flecks/http/server.stats'));
|
||||
// Inline the main entrypoint (nice for FCP).
|
||||
config
|
||||
.plugin('inline-chunks')
|
||||
.use(InlineChunkHtmlPlugin, [HtmlWebpackPlugin, [/^assets\/index(\.[^.]*)?\.js$/]]);
|
||||
};
|
||||
};
|
||||
// Neutrino configuration.
|
||||
const config = {
|
||||
options: {
|
||||
|
@ -25,48 +119,12 @@ module.exports = (async () => {
|
|||
root: FLECKS_CORE_ROOT,
|
||||
},
|
||||
use: [
|
||||
({config}) => {
|
||||
config
|
||||
.plugin('environment')
|
||||
.use(EnvironmentPlugin, [{
|
||||
FLECKS_CORE_BUILD_TARGET: 'client',
|
||||
}]);
|
||||
},
|
||||
await targets(flecks),
|
||||
await build(),
|
||||
],
|
||||
};
|
||||
// Compile code.
|
||||
const compiler = flecks.invokeFleck(
|
||||
'@flecks/http/server.compiler',
|
||||
flecks.get('@flecks/http/server.compiler'),
|
||||
);
|
||||
if (compiler) {
|
||||
config.use.push(compiler);
|
||||
}
|
||||
else {
|
||||
// Use neutrino's web middleware by default.
|
||||
config.use.push(web({
|
||||
clean: false,
|
||||
hot: false,
|
||||
html: {
|
||||
inject: false,
|
||||
template: flecks.buildConfig('template.ejs'),
|
||||
},
|
||||
style: {
|
||||
extract: {
|
||||
enabled: false,
|
||||
},
|
||||
style: {
|
||||
injectType: 'lazyStyleTag',
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
// Configure dev server.
|
||||
config.use.push(devServer(flecks));
|
||||
// Build the client runtime.
|
||||
config.use.push(await runtime(flecks));
|
||||
// Output configuration.
|
||||
config.use.push(outputs());
|
||||
return config;
|
||||
})();
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
|
||||
module.exports = () => ({config}) => {
|
||||
const isProduction = 'production' === config.get('mode');
|
||||
// Emit node buffer builtin.
|
||||
config.node
|
||||
.set('Buffer', true);
|
||||
// Source maps.
|
||||
config.module
|
||||
.rule('maps')
|
||||
.test(/\.js$/)
|
||||
.enforce('pre')
|
||||
.use('source-map-loader')
|
||||
.loader('source-map-loader');
|
||||
config.devtool(isProduction ? 'source-map' : 'eval-source-map');
|
||||
// Asset naming.
|
||||
config.output
|
||||
.chunkFilename(isProduction ? 'assets/[name].[contenthash:8].js' : 'assets/[name].js');
|
||||
config
|
||||
.plugin('inline-chunks')
|
||||
.use(InlineChunkHtmlPlugin, [HtmlWebpackPlugin, [/^assets\/index(\.[^.]*)?\.js$/]]);
|
||||
};
|
|
@ -22,6 +22,7 @@ module.exports = async (flecks) => {
|
|||
const importLoader = await fullresolve('@flecks/http', 'import-loader');
|
||||
const tests = await realpath(R.resolve(join(flecks.resolve('@flecks/http'), 'tests')));
|
||||
return (neutrino) => {
|
||||
const {config} = neutrino;
|
||||
const {resolver} = httpFlecks;
|
||||
const paths = Object.entries(resolver);
|
||||
const source = [
|
||||
|
@ -53,7 +54,7 @@ module.exports = async (flecks) => {
|
|||
source.push('}');
|
||||
source.push('');
|
||||
// Create runtime.
|
||||
neutrino.config.module
|
||||
config.module
|
||||
.rule(runtime)
|
||||
.test(runtime)
|
||||
.use('runtime/http')
|
||||
|
@ -61,11 +62,11 @@ module.exports = async (flecks) => {
|
|||
.options({
|
||||
source: source.join('\n'),
|
||||
});
|
||||
neutrino.config.resolve.alias
|
||||
config.resolve.alias
|
||||
.set('@flecks/http/runtime$', runtime);
|
||||
flecks.runtimeCompiler('http', neutrino);
|
||||
// Handle runtime import.
|
||||
neutrino.config.module
|
||||
config.module
|
||||
.rule(entry)
|
||||
.test(entry)
|
||||
.use('entry/http')
|
||||
|
@ -75,7 +76,7 @@ module.exports = async (flecks) => {
|
|||
if (Object.keys(aliases).length > 0) {
|
||||
Object.entries(aliases)
|
||||
.forEach(([from, to]) => {
|
||||
neutrino.config.resolve.alias
|
||||
config.resolve.alias
|
||||
.set(from, to);
|
||||
});
|
||||
}
|
||||
|
@ -104,10 +105,10 @@ module.exports = async (flecks) => {
|
|||
});
|
||||
// Test entrypoint.
|
||||
if (testPaths.length > 0) {
|
||||
const testEntry = neutrino.config.entry('test').clear();
|
||||
const testEntry = config.entry('test').clear();
|
||||
testPaths.forEach(([, path]) => testEntry.add(path));
|
||||
}
|
||||
neutrino.config.module
|
||||
config.module
|
||||
.rule(tests)
|
||||
.test(tests)
|
||||
.use('runtime/test')
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
const {dirname, join} = require('path');
|
||||
const {realpath} = require('fs/promises');
|
||||
|
||||
const {require: R} = require('@flecks/core/server');
|
||||
|
||||
const {
|
||||
FLECKS_CORE_ROOT = process.cwd(),
|
||||
} = process.env;
|
||||
|
||||
module.exports = async (flecks) => {
|
||||
const root = await realpath(dirname(R.resolve(join(flecks.resolve('@flecks/http'), 'entry.js'))));
|
||||
return (neutrino) => {
|
||||
const {options} = neutrino;
|
||||
const {output: originalOutput} = options;
|
||||
neutrino.config.resolve.modules.merge([
|
||||
join(FLECKS_CORE_ROOT, 'node_modules'),
|
||||
'node_modules',
|
||||
]);
|
||||
options.root = root;
|
||||
options.source = '.';
|
||||
options.mains.index = 'entry';
|
||||
options.mains.tests = {
|
||||
entry: './client/tests',
|
||||
title: 'Testbed',
|
||||
};
|
||||
options.output = join(originalOutput, flecks.get('@flecks/http/server.output'));
|
||||
};
|
||||
};
|
|
@ -1,5 +1,8 @@
|
|||
import {D, Hooks} from '@flecks/core';
|
||||
import {Flecks, spawnWith} from '@flecks/core/server';
|
||||
import fontLoader from '@neutrinojs/font-loader';
|
||||
import imageLoader from '@neutrinojs/image-loader';
|
||||
import styleLoader from '@neutrinojs/style-loader';
|
||||
|
||||
import {configSource, inlineConfig} from './config';
|
||||
import {createHttpServer} from './http';
|
||||
|
@ -8,6 +11,18 @@ const debug = D('@flecks/http/server');
|
|||
|
||||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.build': (target, config) => {
|
||||
config.use.push(styleLoader({
|
||||
extract: {
|
||||
enabled: false,
|
||||
},
|
||||
style: {
|
||||
injectType: 'lazyStyleTag',
|
||||
},
|
||||
}));
|
||||
config.use.push(fontLoader());
|
||||
config.use.push(imageLoader());
|
||||
},
|
||||
'@flecks/core.build.alter': (neutrinoConfigs, flecks) => {
|
||||
// Bail if there's no http build.
|
||||
if (!neutrinoConfigs.http) {
|
||||
|
@ -60,7 +75,11 @@ export default {
|
|||
/**
|
||||
* (webpack-dev-server) Webpack stats output.
|
||||
*/
|
||||
devStats: 'minimal',
|
||||
devStats: {
|
||||
chunks: false,
|
||||
colors: true,
|
||||
modules: false,
|
||||
},
|
||||
/**
|
||||
* Host to bind.
|
||||
*/
|
||||
|
@ -73,6 +92,14 @@ export default {
|
|||
* Port to bind.
|
||||
*/
|
||||
port: 32340,
|
||||
/**
|
||||
* Webpack stats configuration when building HTTP target.
|
||||
*/
|
||||
stats: {
|
||||
chunks: false,
|
||||
colors: true,
|
||||
modules: false,
|
||||
},
|
||||
/**
|
||||
* Proxies to trust.
|
||||
*
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
const {join} = require('path');
|
||||
|
||||
module.exports = {
|
||||
aliases: {
|
||||
'react-dom': '@hot-loader/react-dom',
|
||||
},
|
||||
babel: {
|
||||
plugins: [
|
||||
join(__dirname, '..', 'style-loader'),
|
||||
],
|
||||
presets: [
|
||||
'@babel/preset-react',
|
||||
],
|
||||
|
|
|
@ -38,12 +38,17 @@
|
|||
"router/server.js.map",
|
||||
"server.js",
|
||||
"server.js.map",
|
||||
"src"
|
||||
"src",
|
||||
"style-loader.js",
|
||||
"style-loader.js.map"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.17.0",
|
||||
"@babel/types": "^7.17.0",
|
||||
"@flecks/core": "^1.3.0",
|
||||
"@hot-loader/react-dom": "^17.0.1",
|
||||
"@neutrinojs/react": "^9.4.0",
|
||||
"babel-merge": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"history": "^5.3.0",
|
||||
"prop-types": "^15.7.2",
|
||||
|
|
|
@ -1,28 +1,19 @@
|
|||
import {Hooks} from '@flecks/core';
|
||||
import react from '@neutrinojs/react';
|
||||
|
||||
import ssr from './ssr';
|
||||
|
||||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/http/server.compiler': (flecks) => (
|
||||
react({
|
||||
clean: false,
|
||||
hot: false,
|
||||
html: {
|
||||
inject: false,
|
||||
template: flecks.buildConfig('template.ejs'),
|
||||
},
|
||||
style: {
|
||||
extract: {
|
||||
enabled: false,
|
||||
},
|
||||
style: {
|
||||
injectType: 'lazyStyleTag',
|
||||
},
|
||||
},
|
||||
})
|
||||
),
|
||||
'@flecks/core.build': (target, config) => {
|
||||
// Resolution.
|
||||
config.use.push(({config}) => {
|
||||
config.resolve.alias
|
||||
.set('react-native', 'react-native-web');
|
||||
config.resolve.extensions
|
||||
.prepend('.web.js')
|
||||
.prepend('.web.jsx');
|
||||
});
|
||||
},
|
||||
'@flecks/http/server.stream.html': (stream, req, flecks) => (
|
||||
flecks.get('@flecks/react.ssr') ? ssr(stream, req, flecks) : stream
|
||||
),
|
||||
|
|
22
packages/react/src/style-loader.js
Normal file
22
packages/react/src/style-loader.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const parser = require('@babel/parser');
|
||||
const types = require('@babel/types');
|
||||
|
||||
let id = 0;
|
||||
|
||||
module.exports = () => ({
|
||||
visitor: {
|
||||
/* eslint-disable no-param-reassign */
|
||||
ImportDeclaration(path) {
|
||||
if (path.node.source.value.match(/\.s?css$/)) {
|
||||
let defaultSpecifier = path.node.specifiers.find(types.isImportDefaultSpecifier);
|
||||
if (!defaultSpecifier) {
|
||||
defaultSpecifier = types.importDefaultSpecifier(types.identifier(`LATUS_STYLES_${id++}`));
|
||||
path.node.specifiers.unshift(defaultSpecifier);
|
||||
}
|
||||
const {name} = defaultSpecifier.local;
|
||||
path.insertAfter(parser.parse(`if ('undefined' !== typeof document) ${name}.use();`));
|
||||
}
|
||||
},
|
||||
/* eslint-enable no-param-reassign */
|
||||
},
|
||||
});
|
|
@ -2,12 +2,6 @@ import {Hooks} from '@flecks/core';
|
|||
|
||||
export default {
|
||||
[Hooks]: {
|
||||
/**
|
||||
* Define neutrino compilation middleware (e.g. @neutrinojs/react).
|
||||
*/
|
||||
'@flecks/server.compiler': () => {
|
||||
return require('@neutrinojs/node');
|
||||
},
|
||||
/**
|
||||
* Define sequential actions to run when the server comes up.
|
||||
*/
|
||||
|
@ -16,4 +10,3 @@ export default {
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"dependencies": {
|
||||
"@flecks/core": "^1.3.0",
|
||||
"@neutrinojs/banner": "^9.5.0",
|
||||
"@neutrinojs/node": "^9.4.0",
|
||||
"@neutrinojs/clean": "^9.5.0",
|
||||
"@neutrinojs/start-server": "^9.5.0",
|
||||
"debug": "^4.3.3",
|
||||
"loader-utils": "^1.4.0",
|
||||
|
|
|
@ -19,6 +19,14 @@ export default {
|
|||
* Whether to start the server after building.
|
||||
*/
|
||||
start: true,
|
||||
/**
|
||||
* Webpack stats configuration when building server target.
|
||||
*/
|
||||
stats: {
|
||||
chunks: false,
|
||||
colors: true,
|
||||
modules: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,13 +6,14 @@ const {require: R} = require('@flecks/core/server');
|
|||
module.exports = async (flecks) => {
|
||||
const runtime = await realpath(R.resolve(join(flecks.resolve('@flecks/server'), 'runtime')));
|
||||
return (neutrino) => {
|
||||
const {config, resolver} = flecks;
|
||||
const {config, options} = neutrino;
|
||||
const {resolver} = flecks;
|
||||
// Inject flecks configuration.
|
||||
const paths = Object.keys(resolver);
|
||||
const source = [
|
||||
"process.env.FLECKS_CORE_BUILD_TARGET = 'server';",
|
||||
'module.exports = (async () => ({',
|
||||
` config: ${JSON.stringify(config)},`,
|
||||
` config: ${JSON.stringify(flecks.config)},`,
|
||||
' flecks: Object.fromEntries(await Promise.all([',
|
||||
paths.map((path) => ` ['${path}', import('${path}')]`).join(',\n'),
|
||||
' ].map(async ([path, M]) => [path, await M]))),',
|
||||
|
@ -28,7 +29,7 @@ module.exports = async (flecks) => {
|
|||
source.push(' module.hot.addStatusHandler((status) => {');
|
||||
source.push(' if ("idle" === status) {');
|
||||
source.push(' require("glob")(');
|
||||
source.push(` join('${neutrino.options.output}', \`*\${previousHash}.hot-update.*\`),`);
|
||||
source.push(` join('${options.output}', \`*\${previousHash}.hot-update.*\`),`);
|
||||
source.push(' async (error, disposing) => {');
|
||||
source.push(' if (error) {');
|
||||
source.push(' throw error;');
|
||||
|
@ -49,8 +50,7 @@ module.exports = async (flecks) => {
|
|||
});
|
||||
source.push('}');
|
||||
// Create runtime.
|
||||
const entries = neutrino.config.entry('index');
|
||||
neutrino.config.module
|
||||
config.module
|
||||
.rule(runtime)
|
||||
.test(runtime)
|
||||
.use('runtime')
|
||||
|
@ -63,19 +63,15 @@ module.exports = async (flecks) => {
|
|||
'@flecks/server/runtime',
|
||||
/^@babel\/runtime\/helpers\/esm/,
|
||||
];
|
||||
neutrino.config.resolve.alias
|
||||
config.resolve.alias
|
||||
.set('@flecks/server/runtime$', runtime);
|
||||
flecks.runtimeCompiler('server', neutrino, allowlist);
|
||||
// Rewrite to signals for HMR.
|
||||
if ('production' !== neutrino.config.get('mode')) {
|
||||
if ('production' !== config.get('mode')) {
|
||||
allowlist.push(/^webpack/);
|
||||
if (entries.has(`${R.resolve('webpack/hot/poll')}?1000`)) {
|
||||
entries.delete(`${R.resolve('webpack/hot/poll')}?1000`);
|
||||
entries.add('webpack/hot/signal');
|
||||
}
|
||||
}
|
||||
// Externalize the rest.
|
||||
const nodeExternals = R('webpack-node-externals');
|
||||
neutrino.config.externals(nodeExternals({allowlist}));
|
||||
config.externals(nodeExternals({allowlist}));
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const {join} = require('path');
|
||||
|
||||
const {D} = require('@flecks/core');
|
||||
const {Flecks} = require('@flecks/core/server');
|
||||
const {Flecks, require: R} = require('@flecks/core/server');
|
||||
const banner = require('@neutrinojs/banner');
|
||||
const node = require('@neutrinojs/node');
|
||||
const clean = require('@neutrinojs/clean');
|
||||
const startServer = require('@neutrinojs/start-server');
|
||||
|
||||
const runtime = require('./runtime');
|
||||
|
@ -27,46 +27,77 @@ module.exports = (async () => {
|
|||
start: isStarting,
|
||||
} = flecks.get('@flecks/server');
|
||||
|
||||
const entry = (neutrino) => {
|
||||
const entries = neutrino.config.entry('index');
|
||||
entries.delete(join(FLECKS_CORE_ROOT, 'src', 'index'));
|
||||
const server = (neutrino) => {
|
||||
const {config, options} = neutrino;
|
||||
const isProduction = 'production' === config.get('mode');
|
||||
neutrino.use(banner());
|
||||
neutrino.use(clean({cleanStaleWebpackAssets: false}));
|
||||
// Entrypoints.
|
||||
config.context(options.root);
|
||||
const entries = config.entry('index');
|
||||
if (!isProduction && hot) {
|
||||
config
|
||||
.plugin('hot')
|
||||
.use(R.resolve('webpack/lib/HotModuleReplacementPlugin'));
|
||||
entries.add('webpack/hot/signal');
|
||||
}
|
||||
entries.add('@flecks/server/entry');
|
||||
// Fold in existing source maps.
|
||||
config.module
|
||||
.rule('maps')
|
||||
.test(/\.js$/)
|
||||
.enforce('pre')
|
||||
.use('source-map-loader')
|
||||
.loader('source-map-loader');
|
||||
// Resolution.
|
||||
config.resolve.extensions
|
||||
.merge([
|
||||
'.wasm',
|
||||
...options.extensions.map((ext) => `.${ext}`),
|
||||
'.json',
|
||||
]);
|
||||
// Reporting.
|
||||
config.stats(flecks.get('@flecks/server.stats'));
|
||||
// Outputs.
|
||||
config.output
|
||||
.path(options.output)
|
||||
.libraryTarget('commonjs2');
|
||||
config.node
|
||||
.set('__dirname', false)
|
||||
.set('__filename', false);
|
||||
config
|
||||
.devtool('source-map')
|
||||
.target('node');
|
||||
};
|
||||
|
||||
// Augment the application-starting configuration.
|
||||
const start = (neutrino) => {
|
||||
if (isStarting) {
|
||||
neutrino.use(startServer({name: 'index.js'}));
|
||||
}
|
||||
if (!neutrino.config.plugins.has('start-server')) {
|
||||
return;
|
||||
}
|
||||
neutrino.config
|
||||
.plugin('start-server')
|
||||
.tap((args) => {
|
||||
const options = args[0];
|
||||
options.keyboard = false;
|
||||
// HMR.
|
||||
options.signal = !!hot;
|
||||
// Debugging.
|
||||
if (inspect) {
|
||||
options.nodeArgs.push('--inspect');
|
||||
}
|
||||
// Profiling.
|
||||
if (profile) {
|
||||
options.nodeArgs.push('--prof');
|
||||
}
|
||||
// Bail hard on unhandled rejections and report.
|
||||
options.nodeArgs.push('--unhandled-rejections=strict');
|
||||
options.nodeArgs.push('--trace-uncaught');
|
||||
return args;
|
||||
});
|
||||
};
|
||||
// Really dumb that I can't just pass these in.
|
||||
neutrino.config
|
||||
.plugin('start-server')
|
||||
.tap((args) => {
|
||||
const options = args[0];
|
||||
options.keyboard = false;
|
||||
// HMR.
|
||||
options.signal = !!hot;
|
||||
// Debugging.
|
||||
if (inspect) {
|
||||
options.nodeArgs.push('--inspect');
|
||||
}
|
||||
// Profiling.
|
||||
if (profile) {
|
||||
options.nodeArgs.push('--prof');
|
||||
}
|
||||
// Bail hard on unhandled rejections and report.
|
||||
options.nodeArgs.push('--unhandled-rejections=strict');
|
||||
options.nodeArgs.push('--trace-uncaught');
|
||||
return args;
|
||||
});
|
||||
|
||||
const compiler = flecks.invokeFleck(
|
||||
'@flecks/server.compiler',
|
||||
flecks.get('@flecks/server.compiler'),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const config = {
|
||||
options: {
|
||||
|
@ -74,24 +105,11 @@ module.exports = (async () => {
|
|||
root: FLECKS_CORE_ROOT,
|
||||
},
|
||||
use: [
|
||||
entry,
|
||||
server,
|
||||
start,
|
||||
],
|
||||
};
|
||||
|
||||
if (compiler) {
|
||||
config.use.unshift(compiler);
|
||||
}
|
||||
else {
|
||||
config.use.unshift((neutrino) => {
|
||||
// Default to not starting application on build.
|
||||
neutrino.config.plugins.delete('start-server');
|
||||
});
|
||||
config.use.unshift(node({
|
||||
clean: false,
|
||||
hot,
|
||||
}));
|
||||
}
|
||||
// Stub out non-server-friendly modules on the server.
|
||||
const stubs = flecks.stubs();
|
||||
if (Object.keys(stubs).length > 0) {
|
||||
|
@ -130,8 +148,8 @@ module.exports = (async () => {
|
|||
config.use.push(await runtime(flecks));
|
||||
|
||||
// Give the resolver a helping hand.
|
||||
config.use.push((neutrino) => {
|
||||
neutrino.config.resolve.modules.merge([
|
||||
config.use.push(({config}) => {
|
||||
config.resolve.modules.merge([
|
||||
join(FLECKS_CORE_ROOT, 'node_modules'),
|
||||
'node_modules',
|
||||
]);
|
||||
|
|
Loading…
Reference in New Issue
Block a user