build: refactor

This commit is contained in:
cha0s 2021-03-22 02:53:54 -05:00
parent d4fd51b26d
commit 8745ac5f45
26 changed files with 1459 additions and 355 deletions

View File

@ -8,7 +8,7 @@
"latus-build": "./build.js"
},
"scripts": {
"build": "LATUS_ESLINT_CONFIG=./.eslintrc.js LATUS_POSTCSS_CONFIG=./src/build/postcss.config.js LATUS_WEBPACK_CONFIG=./src/build/webpack.config.js NODE_PATH=./node_modules webpack --config ./webpack.config.js --mode production",
"build": "LATUS_BABEL_CONFIG=./src/build/.babelrc.js LATUS_ESLINT_CONFIG=./.eslintrc.js LATUS_POSTCSS_CONFIG=./src/build/postcss.config.js LATUS_WEBPACK_CONFIG=./src/build/webpack.config.js NODE_PATH=./node_modules webpack --config ./webpack.config.js --mode production",
"fp": "npm unpublish --force $(node -e 'const {name, version} = require(`./package.json`); process.stdout.write(`${name}@${version}`)') && npm publish",
"lint": "NODE_PATH=./node_modules eslint --config ./src/build/.eslintrc.js --format codeframe --ext mjs,js .",
"test": "yarn --silent run build --display none && mocha --colors test.js"
@ -30,6 +30,7 @@
"@neutrinojs/banner": "^9.4.0",
"@neutrinojs/copy": "^9.4.0",
"@neutrinojs/mocha": "^9.4.0",
"babel-plugin-webpack-alias": "^2.1.2",
"chai": "4.2.0",
"commander": "^7.1.0",
"eslint": "^7",

View File

@ -23,6 +23,7 @@ const localConfig = (filename) => {
const build = async (args = []) => {
const {production} = program.opts();
const babelConfigFile = localConfig('.babelrc.js');
const eslintConfigFile = localConfig('.eslintrc.js');
const eslintDefaultsFile = localConfig('.eslint.defaults.js');
const neutrinoConfigFile = localConfig('.neutrinorc.js');
@ -41,6 +42,7 @@ const build = async (args = []) => {
{
env: {
NODE_PATH: './node_modules',
LATUS_BABEL_CONFIG: babelConfigFile,
LATUS_ESLINT_CONFIG: eslintConfigFile,
LATUS_ESLINT_DEFAULTS: eslintDefaultsFile,
LATUS_NEUTRINO_CONFIG: neutrinoConfigFile,

View File

@ -0,0 +1,20 @@
const {
LATUS_WEBPACK_CONFIG = require.resolve('./webpack.config.js'),
} = process.env;
module.exports = (api) => {
api.cache(false);
return {
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-private-methods',
'@babel/plugin-syntax-jsx',
[
'babel-plugin-webpack-alias',
{
config: LATUS_WEBPACK_CONFIG,
},
]
],
};
};

View File

@ -1,4 +1,5 @@
const {
LATUS_BABEL_CONFIG = require.resolve('./.babelrc.js'),
LATUS_WEBPACK_CONFIG = require.resolve('./webpack.config.js'),
} = process.env;
@ -16,11 +17,7 @@ const config = {
parserOptions: {
requireConfigFile: false,
babelOptions: {
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-private-methods',
'@babel/plugin-syntax-jsx',
],
configFile: LATUS_BABEL_CONFIG,
},
},
rules: {

View File

@ -1,14 +1,11 @@
const {basename, dirname, extname, join} = require('path');
const airbnb = require('@neutrinojs/airbnb');
const glob = require('glob');
const mocha = require('@neutrinojs/mocha');
const react = require('@neutrinojs/react');
const nodeExternals = require('webpack-node-externals');
const library = require('./neutrino/library');
const react = require('./neutrino/react');
const {
LATUS_ESLINT_DEFAULTS = require.resolve('./.eslint.defaults.js'),
LATUS_POSTCSS_CONFIG = require.resolve('./postcss.config.js'),
} = process.env;
module.exports = {
@ -20,94 +17,8 @@ module.exports = {
baseConfig: require(LATUS_ESLINT_DEFAULTS),
},
}),
(neutrino) => {
const {files = [], name} = neutrino.options.packageJson;
files
.filter((file) => {
const {source} = neutrino.options;
try {
require.resolve(`${source}/${file}`);
return true;
}
catch (error) {
const ext = extname(file);
try {
require.resolve(`${source}/${dirname(file)}/${basename(file, ext)}/index${ext}`);
return true;
}
catch (error) {
return false;
}
}
})
.forEach((file) => {
const isIndex = 'index.js' === file;
const trimmed = join(dirname(file), basename(file, extname(file)));
neutrino.options.mains[trimmed] = {entry: isIndex ? file : `./src/${trimmed}`};
});
const testPaths = glob.sync('./test/*.js');
if (testPaths.length > 0) {
const testEntry = neutrino.config.entry('test').clear();
testPaths.forEach((path) => testEntry.add(path));
}
const cssPaths = glob.sync('./src/**/*.{css,scss}');
if (cssPaths.length > 0) {
const cssEntry = neutrino.config.entry('index.css').clear();
cssPaths.forEach((path) => cssEntry.add(path));
}
neutrino.options.output = '.';
react({
clean: false,
hot: false,
style: {
extract: {
enabled: false,
},
test: /\.(css|sass|scss)$/,
modulesTest: /\.module\.(css|sass|scss)$/,
loaders: [
{
loader: 'postcss-loader',
useId: 'postcss',
options: {
config: {
path: dirname(LATUS_POSTCSS_CONFIG),
},
},
},
{
loader: 'sass-loader',
useId: 'sass',
},
],
},
})(neutrino);
Object.keys(neutrino.options.mains).forEach((main) => {
neutrino.config.plugins.delete(`html-${main}`);
});
neutrino.config
.devtool('source-map')
.target('node')
.optimization
.splitChunks(false)
.runtimeChunk(false)
.end()
.output
.filename('[name].js')
.library(name)
.libraryTarget('umd')
.umdNamedDefine(true)
.end()
.node
.set('__dirname', false)
.set('__filename', false);
const options = neutrino.config.module
.rule('compile')
.use('babel')
.get('options');
options.presets[0][1].targets = {esmodules: true};
neutrino.config.externals(nodeExternals({importType: 'umd'}));
},
react(),
library(),
mocha(),
],
};

View File

@ -0,0 +1,65 @@
const {basename, dirname, extname, join} = require('path');
const glob = require('glob');
const nodeExternals = require('webpack-node-externals');
module.exports = () => (neutrino) => {
neutrino.config.output.path(process.cwd());
const {files = []} = neutrino.options.packageJson;
files
.filter((file) => {
const {source} = neutrino.options;
try {
require.resolve(`${source}/${file}`);
return true;
}
catch (error) {
const ext = extname(file);
try {
require.resolve(`${source}/${dirname(file)}/${basename(file, ext)}/index${ext}`);
return true;
}
catch (error) {
return false;
}
}
})
.forEach((file) => {
const trimmed = join(dirname(file), basename(file, extname(file)));
const entry = neutrino.config.entry(trimmed).clear();
entry.add(`./src/${trimmed}`);
});
const testPaths = glob.sync('./test/*.js');
if (testPaths.length > 0) {
const testEntry = neutrino.config.entry('test').clear();
testPaths.forEach((path) => testEntry.add(path));
}
const cssPaths = glob.sync('./src/**/*.{css,scss}');
if (cssPaths.length > 0) {
const cssEntry = neutrino.config.entry('index.css').clear();
cssPaths.forEach((path) => cssEntry.add(path));
}
const {name} = neutrino.options.packageJson;
neutrino.config
.devtool('source-map')
.target('node')
.optimization
.splitChunks(false)
.runtimeChunk(false)
.end()
.output
.filename('[name].js')
.library(name)
.libraryTarget('umd')
.umdNamedDefine(true)
.end()
.node
.set('__dirname', false)
.set('__filename', false);
const options = neutrino.config.module
.rule('compile')
.use('babel')
.get('options');
options.presets[0][1].targets = {esmodules: true};
neutrino.config.externals(nodeExternals({importType: 'umd'}));
};

View File

@ -0,0 +1,46 @@
const {dirname} = require('path');
const react = require('@neutrinojs/react');
const {
LATUS_BABEL_CONFIG = require.resolve('./.babelrc.js'),
LATUS_POSTCSS_CONFIG = require.resolve('./postcss.config.js'),
} = process.env;
module.exports = () => (neutrino) => {
react({
babel: {
configFile: LATUS_BABEL_CONFIG,
},
clean: false,
hot: false,
html: {
inject: false,
},
style: {
extract: {
enabled: false,
},
test: /\.(css|sass|scss)$/,
modulesTest: /\.module\.(css|sass|scss)$/,
loaders: [
{
loader: 'postcss-loader',
useId: 'postcss',
options: {
config: {
path: dirname(LATUS_POSTCSS_CONFIG),
},
},
},
{
loader: 'sass-loader',
useId: 'sass',
},
],
},
})(neutrino);
Object.keys(neutrino.options.mains).forEach((main) => {
neutrino.config.plugins.delete(`html-${main}`);
});
};

View File

@ -769,6 +769,34 @@ babel-plugin-dynamic-import-node@^2.3.3:
dependencies:
object.assign "^4.1.0"
babel-plugin-webpack-alias@^2.1.2:
version "2.1.2"
resolved "http://npm.cha0sdev/babel-plugin-webpack-alias/-/babel-plugin-webpack-alias-2.1.2.tgz#05a1ba23c28595660fb6ea5736424fc596b4a247"
integrity sha1-BaG6I8KFlWYPtupXNkJPxZa0okc=
dependencies:
babel-types "^6.14.0"
find-up "^2.0.0"
lodash.some "^4.5.1"
lodash.template "^4.3.0"
babel-runtime@^6.26.0:
version "6.26.0"
resolved "http://npm.cha0sdev/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
babel-types@^6.14.0:
version "6.26.0"
resolved "http://npm.cha0sdev/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
dependencies:
babel-runtime "^6.26.0"
esutils "^2.0.2"
lodash "^4.17.4"
to-fast-properties "^1.0.3"
balanced-match@^1.0.0:
version "1.0.0"
resolved "http://npm.cha0sdev/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@ -1264,6 +1292,11 @@ core-js-pure@^3.0.0:
resolved "http://npm.cha0sdev/core-js-pure/-/core-js-pure-3.8.3.tgz#10e9e3b2592ecaede4283e8f3ad7020811587c02"
integrity sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA==
core-js@^2.4.0:
version "2.6.12"
resolved "http://npm.cha0sdev/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-util-is@~1.0.0:
version "1.0.2"
resolved "http://npm.cha0sdev/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@ -2856,6 +2889,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "http://npm.cha0sdev/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "http://npm.cha0sdev/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
@ -2866,7 +2904,27 @@ lodash.omit@^4.5.0:
resolved "http://npm.cha0sdev/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60"
integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=
lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20:
lodash.some@^4.5.1:
version "4.6.0"
resolved "http://npm.cha0sdev/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=
lodash.template@^4.3.0:
version "4.5.0"
resolved "http://npm.cha0sdev/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
dependencies:
lodash._reinterpolate "^3.0.0"
lodash.templatesettings "^4.0.0"
lodash.templatesettings@^4.0.0:
version "4.2.0"
resolved "http://npm.cha0sdev/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
dependencies:
lodash._reinterpolate "^3.0.0"
lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4:
version "4.17.20"
resolved "http://npm.cha0sdev/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
@ -3723,6 +3781,11 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "http://npm.cha0sdev/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "http://npm.cha0sdev/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
@ -4348,6 +4411,11 @@ to-arraybuffer@^1.0.0:
resolved "http://npm.cha0sdev/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
to-fast-properties@^1.0.3:
version "1.0.3"
resolved "http://npm.cha0sdev/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "http://npm.cha0sdev/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"

View File

@ -24,6 +24,8 @@
"test.js.map"
],
"dependencies": {
"@neutrinojs/copy": "^9.4.0",
"@neutrinojs/node": "^9.1.0",
"autoprefixer": "^9.8.6",
"debug": "4.3.1",
"js-yaml": "3.14.0",
@ -32,6 +34,8 @@
"lodash.set": "^4.3.2",
"lodash.without": "^4.4.0",
"mkdirp": "^1.0.4",
"webpack": "^4",
"webpack-node-externals": "2.5.2",
"webpack-virtual-modules": "^0.4.1"
},
"devDependencies": {

121
packages/core/src/build.js Normal file
View File

@ -0,0 +1,121 @@
import {LatusPlugin} from './latus-plugin';
const {
LATUS_ESLINT_DEFAULTS = require.resolve('@latus/build/build/.eslint.defaults.js'),
} = process.env;
export default (latus) => (neutrino) => {
// eslint-disable-next-line no-eval
const r = eval('require');
const airbnb = r('@neutrinojs/airbnb');
airbnb({
eslint: {
cache: false,
baseConfig: r(LATUS_ESLINT_DEFAULTS),
},
})(neutrino);
const clean = r('@neutrinojs/clean');
clean({
cleanOnceBeforeBuildPatterns: ['**/*.hot-update.*'],
})(neutrino);
const copy = r('@neutrinojs/copy');
copy({
patterns: [{
from: 'src/assets',
to: 'http',
}],
})(neutrino);
const {EnvironmentPlugin} = r('webpack');
neutrino.config
.plugin('environment')
.use(EnvironmentPlugin, [{
SIDE: 'server',
}]);
const defaults = Object.keys(latus.originalConfig)
.map((plugin) => {
const config = {};
[plugin, `${plugin}/server`].forEach((path) => {
try {
r.resolve(path);
config[path] = {};
}
// eslint-disable-next-line no-empty
catch (error) {}
});
return config;
})
.filter((config) => !!config)
.reduce((r, o) => ({...r, ...o}), {});
const config = Object.fromEntries(
Object.keys(defaults)
.map((path) => [
path,
latus.get(path),
]),
);
neutrino.config
.plugin('latus')
.use(LatusPlugin(
neutrino,
() => config,
(plugin, modulesObject) => {
plugin.writeModule('/%/latus/server/virtual', [
'global.$$latus = {',
` config: ${JSON.stringify(config)},`,
` modules: ${modulesObject},`,
'};',
'if (module.hot) {',
' Object.keys(global.$$latus.modules).forEach((key) => {',
' module.hot.accept(key, () => {',
" console.log('kesy!');",
' });',
' });',
'}',
].join('\n'));
},
));
neutrino.config
.entry('index')
.add('/%/latus/server/virtual');
const nodeExternals = r('webpack-node-externals');
neutrino.config.externals(nodeExternals());
const mocha = r('@neutrinojs/mocha');
mocha()(neutrino);
const node = r('@neutrinojs/node');
node({
hot: false,
})(neutrino);
if (process.env.LATUS_LINTING) {
return;
}
neutrino.config
.entry('index')
.add('@latus/core/start');
if ('production' !== neutrino.config.get('mode')) {
neutrino.config
.entry('index')
.prepend('dotenv/config');
}
if (process.argv.find((arg) => '--start-server' === arg)) {
neutrino.config
.plugin('start-server')
.tap((args) => {
const options = args[0];
options.signal = true;
const inspectArg = process.argv.find((arg) => -1 !== arg.indexOf('--inspect'));
if (inspectArg) {
options.nodeArgs.push(inspectArg);
}
const profArg = process.argv.find((arg) => -1 !== arg.indexOf('--prof'));
if (profArg) {
options.nodeArgs.push(profArg);
}
options.nodeArgs.push('--experimental-repl-await');
options.nodeArgs.push('--unhandled-rejections=strict');
return args;
});
}
else {
neutrino.config.plugins.delete('start-server');
}
};

View File

@ -1,5 +1,3 @@
import {LatusPlugin} from './latus-plugin';
export {
unique as arrayUnique,
flatten as arrayFlatten,
@ -13,66 +11,13 @@ export {compose, fastApply} from './function';
export {decorateWithLatus, gatherWithLatus, default as gather} from './gather';
export {default as Middleware} from './middleware';
export {default as Latus} from './latus';
export {LatusPlugin} from './latus-plugin';
export * from './string';
export {LatusPlugin};
export const Class = class {};
export default {
hooks: {
'@latus/core/build': (configs, latus) => {
// eslint-disable-next-line no-undef
configs.app.use.unshift((neutrino) => {
const defaults = Object.keys(latus.originalConfig)
.map((plugin) => {
const config = {};
[plugin, `${plugin}/server`].forEach((path) => {
try {
// eslint-disable-next-line no-eval
eval('require.resolve')(path);
config[path] = {};
}
// eslint-disable-next-line no-empty
catch (error) {}
});
return config;
})
.filter((config) => !!config)
.reduce((r, o) => ({...r, ...o}), {});
const config = Object.fromEntries(
Object.keys(defaults)
.map((path) => [
path,
latus.get(path),
]),
);
neutrino.config
.plugin('latus')
.use(LatusPlugin(
neutrino,
() => config,
(plugin, modulesObject) => {
plugin.writeModule('/%/latus/server/virtual', [
'global.$$latus = {',
` config: ${JSON.stringify(config)},`,
` modules: ${modulesObject},`,
'};',
'if (module.hot) {',
' Object.keys(global.$$latus.modules).forEach((key) => {',
' module.hot.accept(key, () => {',
" console.log('kesy!');",
' });',
' });',
'}',
].join('\n'));
},
));
neutrino.config
.entry('index')
.add('/%/latus/server/virtual');
});
},
'@latus/core/config': () => ({
id: 'latus',
}),

View File

@ -8,13 +8,10 @@ exports.LatusPlugin = (neutrino, getConfig, write) => class LatusPlugin {
apply(compiler) {
const plugin = new VirtualModulesPlugin();
plugin.apply(compiler);
let babelOptions;
neutrino.config.module
.rule('compile')
.use('babel')
.tap((options) => {
babelOptions = options;
});
const babelOptions = neutrino.config.module
.rules.store.get('compile')
.uses.store.get('babel')
.store.get('options');
// eslint-disable-next-line no-eval
eval('require')('@babel/register')({
plugins: babelOptions.plugins,

View File

@ -1,7 +1,12 @@
import build from './build';
export {default as appdata} from './appdata';
export default {
hooks: {
'@latus/core/build': (configs, latus) => {
configs.server.use.unshift(build(latus));
},
'@latus/core/config': () => ({
up: [],
}),

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@ module.exports.use.push(copy({
patterns: ['entry.js', 'index.ejs', 'tests.js'].map((path) => ({
from: `src/client/${path}`,
to: 'client',
})).concat(['.neutrinorc.js', 'client-plugins.js', 'webpack.config.js'].map((path) => ({
from: `src/build/${path}`,
})).concat({
from: 'src/build',
to: 'build',
}))),
}),
}));

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="<%= htmlWebpackPlugin.options.lang %>">
<head>
<base href="/" />
<meta charset="utf-8">
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<link rel="icon" href="/favicon.png"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="<%= htmlWebpackPlugin.options.appMountId %>">
<div class="debug-container"></div>
</div>
<script src="/latus.config.js"></script>
<%= htmlWebpackPlugin.tags.bodyTags %>
</body>
</html>

View File

@ -1,124 +1,22 @@
const {isAbsolute, join} = require('path');
const {join} = require('path');
const fs = require('fs');
const {Latus} = require('@latus/core');
const web = require('@neutrinojs/web');
const {DefinePlugin, EnvironmentPlugin} = require('webpack');
const {Latus, LatusPlugin} = require('@latus/core');
const VirtualModulesPlugin = require('webpack-virtual-modules');
const clientPlugins = require('./client-plugins');
const outputs = require('./neutrino/outputs');
const targets = require('./neutrino/targets');
const web = require('./neutrino/web');
const virtual = require('./neutrino/virtual');
const latus = Latus.create();
const {
HTTP_DEV_HOST,
HTTP_DEV_PORT,
HTTP_DEV_PUBLIC,
NODE_ENV,
} = process.env;
const client = {
const config = {
use: [
(neutrino) => {
const root = `${__dirname}/..`;
neutrino.options.root = fs.realpathSync(root);
neutrino.options.source = 'client';
neutrino.options.mains.index = 'entry';
neutrino.options.mains.tests = {
entry: './client/tests',
title: 'Mocha tests',
};
const output = 'build';
neutrino.options.output = join(
isAbsolute(output)
? output
: join(process.cwd(), output),
'http',
);
},
(neutrino) => {
web({
clean: false,
hot: false,
html: {
inject: false,
template: `${neutrino.options.root}/client/index.ejs`,
},
})(neutrino);
},
(neutrino) => {
neutrino.config
.plugin('environment')
.use(DefinePlugin, [{
'process.env.SIDE': JSON.stringify('client'),
}]);
},
(neutrino) => {
neutrino.config
.plugin('latus')
.use(LatusPlugin(
neutrino,
() => clientPlugins(latus),
(plugin, modulesObject, paths) => {
const cssPaths = paths
.map((path) => Latus.runtimePath(`${path}/index.css.js`))
.filter((path) => !!path);
const cssAppliers = cssPaths.map((path) => `require('${path}')`).join(';');
plugin.writeModule('node_modules/@latus/core/client/virtual', [
`${cssAppliers}`,
'export default {',
' config: window.$$latusConfig,',
` modules: ${modulesObject},`,
'};',
].join('\n'));
const testPaths = paths
.map((path) => [path, Latus.runtimePath(`${path}/test`)])
.filter(([, path]) => !!path);
plugin.writeModule(`node_modules/@latus/core/tests`, testPaths.map(
([original, path]) => `describe('${original}', () => require('${path}'));`
).join(''));
},
));
neutrino.config.resolve.modules.merge([
join(process.cwd(), 'node_modules'),
'node_modules',
]);
},
targets(),
web(),
virtual(latus),
],
};
latus.invokeFlat('@latus/http/build', client);
client.use.push((neutrino) => {
const {title} = latus.get('@latus/http');
neutrino.config.node
.set('Buffer', true);
neutrino.config.module.rule('compile').include.add(`${process.cwd()}/src`);
neutrino.config.module
.rule('maps')
.test(/\.js$/)
.enforce('pre')
.use('source-map-loader')
.loader('source-map-loader');
neutrino.config
.plugin('html-index')
.tap(([options]) => [{
...options,
title,
}]);
const isProduction = 'production' === neutrino.config.get('mode');
if (!isProduction) {
neutrino.config.devServer
.hot(false)
.host(HTTP_DEV_HOST)
.port(HTTP_DEV_PORT)
.public(HTTP_DEV_PUBLIC);
}
neutrino.config.devtool(isProduction ? 'source-map' : 'eval-source-map');
neutrino.config.output
.chunkFilename(
isProduction ? 'assets/[name].[contenthash:8].js' : 'assets/[name].js',
);
});
latus.invokeFlat('@latus/http/build', config);
config.use.push(outputs(latus));
module.exports = client;
module.exports = config;

View File

@ -0,0 +1,35 @@
const {
HTTP_DEV_HOST,
HTTP_DEV_PORT,
HTTP_DEV_PUBLIC,
} = process.env;
module.exports = (latus) => (neutrino) => {
const isProduction = 'production' === neutrino.config.get('mode');
if (!isProduction) {
neutrino.config.devServer
.hot(false)
.host(HTTP_DEV_HOST)
.port(HTTP_DEV_PORT)
.public(HTTP_DEV_PUBLIC);
}
neutrino.config.node
.set('Buffer', true);
neutrino.config.module
.rule('maps')
.test(/\.js$/)
.enforce('pre')
.use('source-map-loader')
.loader('source-map-loader');
neutrino.config.devtool(isProduction ? 'source-map' : 'eval-source-map');
neutrino.config.output
.chunkFilename(
isProduction ? 'assets/[name].[contenthash:8].js' : 'assets/[name].js',
);
neutrino.config
.plugin('html-index')
.tap(([options]) => [{
...options,
title: latus.get('@latus/http.title'),
}]);
};

View File

@ -0,0 +1,32 @@
/* eslint-disable no-param-reassign */
const {isAbsolute, join} = require('path');
const fs = require('fs');
const {DefinePlugin} = require('webpack');
module.exports = () => (neutrino) => {
neutrino.config
.plugin('environment')
.use(DefinePlugin, [{
'process.env.SIDE': JSON.stringify('client'),
}]);
neutrino.config.resolve.modules.merge([
join(process.cwd(), 'node_modules'),
'node_modules',
]);
const root = join(__dirname, '..', '..');
neutrino.options.root = fs.realpathSync(root);
neutrino.options.source = 'client';
neutrino.options.mains.index = 'entry';
neutrino.options.mains.tests = {
entry: './client/tests',
title: 'Mocha tests',
};
const output = 'build';
neutrino.options.output = join(
isAbsolute(output)
? output
: join(process.cwd(), output),
'http',
);
};

View File

@ -0,0 +1,32 @@
/* eslint-disable no-param-reassign */
const {Latus, LatusPlugin} = require('@latus/core');
const clientPlugins = require('../client-plugins');
module.exports = (latus) => (neutrino) => {
neutrino.config
.plugin('latus')
.use(LatusPlugin(
neutrino,
() => clientPlugins(latus),
(plugin, modulesObject, paths) => {
const cssPaths = paths
.map((path) => Latus.runtimePath(`${path}/index.css.js`))
.filter((path) => !!path);
const cssAppliers = cssPaths.map((path) => `require('${path}')`).join(';');
plugin.writeModule('node_modules/@latus/core/client/virtual', [
`${cssAppliers}`,
'export default {',
' config: window.$$latusConfig,',
` modules: ${modulesObject},`,
'};',
].join('\n'));
const testPaths = paths
.map((path) => [path, Latus.runtimePath(`${path}/test`)])
.filter(([, path]) => !!path);
plugin.writeModule('node_modules/@latus/core/tests', testPaths.map(
([original, path]) => `describe('${original}', () => require('${path}'));`,
).join(''));
},
));
};

View File

@ -0,0 +1,25 @@
/* eslint-disable no-param-reassign */
const web = require('@neutrinojs/web');
const {
LATUS_BABEL_CONFIG = require.resolve('./.babelrc.js'),
} = process.env;
module.exports = () => {
const middleware = (neutrino) => {
web({
babel: {
configFile: LATUS_BABEL_CONFIG,
},
clean: false,
hot: false,
html: {
inject: false,
template: `${neutrino.options.root}/client/index.ejs`,
},
})(neutrino);
neutrino.config.module.rule('compile').include.add(`${process.cwd()}/src`);
};
middleware.isWebMiddleware = true;
return middleware;
};

View File

@ -12,7 +12,7 @@ const {version} = require('../package.json');
await latus.invokeSequential('@latus/http/client/up');
// eslint-disable-next-line no-console
console.log([
' ▄█ ▄████████ ███ ███ █▄ ▄████████ ',
' ▄█ ▄████████ ███ ███ █▄ ▄████████ ',
' ███ ███ ███ ▀█████████▄ ███ ███ ███ ███ ',
' ███ ███ ███ ▀███▀▀██ ███ ███ ███ █▀ ',
' ███ ███ ███ ███ ▀ ███ ███ ███ ',

View File

@ -14,9 +14,12 @@ export default {
},
},
} = latus;
if (process.argv.find((arg) => 'production' === arg)) {
if (
!process.argv.find((arg) => '--watch' === arg)
|| process.argv.find((arg) => 'production' === arg)
) {
// eslint-disable-next-line global-require, no-eval, no-param-reassign
configs.client = eval('require')('./build/.neutrinorc');
configs.http = eval('require')('./build/.neutrinorc');
}
else {
const binary = `$(npm --prefix ${process.cwd()} bin)/webpack-dev-server`;

View File

@ -0,0 +1,21 @@
const react = require('./react');
module.exports = (config) => {
const webIndex = config.use.findIndex((m) => m.isWebMiddleware);
if (-1 !== webIndex) {
config.use.splice(webIndex, 1, react());
}
config.use.push((neutrino) => {
[
'components',
'context',
'fonts',
'hooks',
'images',
'scss',
].forEach((path) => {
neutrino.config.resolve.alias
.set(path, `${process.cwd()}/src/react/${path}`);
});
});
};

47
packages/react/src/build/react.js vendored Normal file
View File

@ -0,0 +1,47 @@
const {dirname} = require('path');
const react = require('@neutrinojs/react');
// eslint-disable-next-line no-eval
const rr = eval('require').resolve;
const {
LATUS_BABEL_CONFIG = rr('@latus/build/build/.bbelrc.js'),
LATUS_POSTCSS_CONFIG = rr('@latus/build/build/postcss.config.js'),
} = process.env;
module.exports = () => (neutrino) => {
react({
babel: {
configFile: LATUS_BABEL_CONFIG,
},
clean: false,
hot: false,
html: {
inject: false,
template: `${neutrino.options.root}/client/index.ejs`,
},
style: {
extract: {
enabled: false,
},
test: /\.(css|sass|scss)$/,
modulesTest: /\.module\.(css|sass|scss)$/,
loaders: [
{
loader: 'postcss-loader',
useId: 'postcss',
options: {
config: {
path: dirname(LATUS_POSTCSS_CONFIG),
},
},
},
{
loader: 'sass-loader',
useId: 'sass',
},
],
},
})(neutrino);
neutrino.config.module.rule('compile').include.add(`${process.cwd()}/src`);
};

View File

@ -1,67 +1,9 @@
const {dirname} = require('path');
const react = require('@neutrinojs/react');
const {
// eslint-disable-next-line no-eval
LATUS_POSTCSS_CONFIG = eval('require').resolve('@latus/build/build/postcss.config.js'),
} = process.env;
const middleware = (neutrino) => {
neutrino.use((neutrino) => {
['compile', 'font', 'image', 'style'].forEach((rule) => {
neutrino.config.module.rules.delete(rule);
});
});
neutrino.use(react({
clean: false,
hot: false,
html: {
inject: false,
template: `${neutrino.options.root}/client/index.ejs`,
},
style: {
extract: {
enabled: false,
},
test: /\.(css|sass|scss)$/,
modulesTest: /\.module\.(css|sass|scss)$/,
loaders: [
{
loader: 'postcss-loader',
useId: 'postcss',
options: {
config: {
path: dirname(LATUS_POSTCSS_CONFIG),
},
},
},
{
loader: 'sass-loader',
useId: 'sass',
},
],
},
}));
neutrino.use((neutrino) => {
[
'components',
'context',
'fonts',
'hooks',
'images',
'scss',
].forEach((path) => {
neutrino.config.resolve.alias
.set(path, `${process.cwd()}/src/react/${path}`);
});
});
};
const httpBuild = require('./build/http');
export default {
hooks: {
'@latus/http/build': (client) => {
client.use.push(middleware);
'@latus/http/build': (config) => {
httpBuild(config);
},
'@latus/http/plugins': (req, {
config: {'@latus/react': {entry}},