feat: centralized build
This commit is contained in:
parent
dfbe25624e
commit
89ccd8148b
7
packages/build/.gitignore
vendored
Normal file
7
packages/build/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
**/*.js
|
||||
**/*.map
|
||||
!/.*
|
||||
!/.neutrinorc.js
|
||||
!/webpack.config.js
|
||||
!src/**/*.js
|
||||
!/test/**/*.js
|
39
packages/build/.neutrinorc.js
Normal file
39
packages/build/.neutrinorc.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const {chmod} = require('fs');
|
||||
const {join} = require('path');
|
||||
|
||||
const banner = require('@neutrinojs/banner');
|
||||
const copy = require('@neutrinojs/copy');
|
||||
|
||||
module.exports = require('./src/build/.neutrinorc');
|
||||
|
||||
module.exports.use.push(banner({
|
||||
banner: '#!/usr/bin/env node',
|
||||
raw: true,
|
||||
pluginId: 'shebang',
|
||||
}))
|
||||
|
||||
module.exports.use.push(({config}) => {
|
||||
config
|
||||
.plugin('executable')
|
||||
.use(class Executable {
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.afterEmit.tapAsync(
|
||||
'Executable',
|
||||
(compilation, callback) => {
|
||||
chmod(join(__dirname, 'build.js'), 0o755, callback);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.use.push(
|
||||
copy({
|
||||
patterns: [{
|
||||
from: 'src/build',
|
||||
to: 'build',
|
||||
}],
|
||||
}),
|
||||
);
|
41
packages/build/package.json
Normal file
41
packages/build/package.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "@latus/build",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"author": "cha0s",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"latus-build": "./build.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "NODE_PATH=./node_modules webpack --config ./webpack.config.js --mode production",
|
||||
"clean": "rm -rf yarn.lock node_modules/* $(node -e \"process.stdout.write(require('./package.json').files.filter((file) => {const parts = file.split('/'); return 1 === parts.length || 'test' !== parts[0];}).join(' '));\")",
|
||||
"forcepub": "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 ./.eslintrc.js --format codeframe --ext mjs,js .",
|
||||
"test": "yarn --silent run build --display none && mocha --colors test.js"
|
||||
},
|
||||
"files": [
|
||||
"build",
|
||||
"build.js",
|
||||
"index.js",
|
||||
"index.js.map",
|
||||
"test.js",
|
||||
"test.js.map"
|
||||
],
|
||||
"dependencies": {
|
||||
"@neutrinojs/airbnb": "^9.4.0",
|
||||
"@neutrinojs/banner": "^9.4.0",
|
||||
"@neutrinojs/copy": "^9.4.0",
|
||||
"@neutrinojs/mocha": "^9.4.0",
|
||||
"chai": "4.2.0",
|
||||
"commander": "^7.1.0",
|
||||
"eslint": "^7",
|
||||
"eslint-import-resolver-webpack": "0.13.0",
|
||||
"mocha": "^8",
|
||||
"neutrino": "^9.4.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"source-map-support": "0.5.19",
|
||||
"webpack": "^4",
|
||||
"webpack-cli": "^3"
|
||||
}
|
||||
}
|
181
packages/build/src/build.js
Executable file
181
packages/build/src/build.js
Executable file
|
@ -0,0 +1,181 @@
|
|||
/* eslint-disable */
|
||||
import {spawn} from 'child_process';
|
||||
import {statSync} from 'fs';
|
||||
import {join, normalize} from 'path';
|
||||
|
||||
import {Command} from 'commander';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
const cwd = normalize(process.cwd());
|
||||
|
||||
const localConfig = (filename) => {
|
||||
let configFile = join(__dirname, 'build', filename);
|
||||
try {
|
||||
const localConfig = join(cwd, filename);
|
||||
statSync(localConfig);
|
||||
configFile = localConfig;
|
||||
}
|
||||
catch (error) {}
|
||||
return configFile;
|
||||
}
|
||||
|
||||
const build = async (args = []) => {
|
||||
const {production} = program.opts();
|
||||
const configFile = localConfig('webpack.config.js');
|
||||
const child = spawn(
|
||||
'webpack',
|
||||
[
|
||||
'--config',
|
||||
configFile,
|
||||
'--mode',
|
||||
production ? 'production' : 'development',
|
||||
]
|
||||
.concat(args),
|
||||
{
|
||||
env: {
|
||||
NODE_PATH: './node_modules',
|
||||
...process.env,
|
||||
},
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
return new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
child.on('exit', (code) => {
|
||||
child.off('error', reject);
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
program
|
||||
.command('build', {isDefault: true})
|
||||
.description('build package')
|
||||
.action(() => build());
|
||||
|
||||
const clean = () => {
|
||||
rimraf.sync(join(cwd, 'node_modules', '*'));
|
||||
rimraf.sync(join(cwd, 'yarn.lock'));
|
||||
const {files} = __non_webpack_require__(join(cwd, 'package.json'));
|
||||
rimraf.sync(
|
||||
files
|
||||
.map((filename) => join(cwd, filename))
|
||||
.join(' '),
|
||||
);
|
||||
};
|
||||
|
||||
program
|
||||
.command('clean')
|
||||
.description('remove node_modules/*, yarn.lock, and build artifacts')
|
||||
.action(clean);
|
||||
|
||||
const unpublish = async () => {
|
||||
const {name, version} = __non_webpack_require__(join(cwd, 'package.json'));
|
||||
const child = spawn(
|
||||
'npm',
|
||||
[
|
||||
'unpublish',
|
||||
'--force',
|
||||
`${name}@${version}`,
|
||||
],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
return new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
child.on('exit', (code) => {
|
||||
child.off('error', reject);
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const publish = async () => {
|
||||
const child = spawn(
|
||||
'npm',
|
||||
[
|
||||
'publish',
|
||||
],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
return new Promise((resolve, reject) => {
|
||||
child.on('error', reject);
|
||||
child.on('exit', (code) => {
|
||||
child.off('error', reject);
|
||||
resolve(code);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
program
|
||||
.command('forcepublish')
|
||||
.alias('fp')
|
||||
.description('force publish to npm')
|
||||
.action(async () => {
|
||||
await unpublish();
|
||||
await publish();
|
||||
});
|
||||
|
||||
const lint = () => {
|
||||
const {production} = program.opts();
|
||||
const configFile = localConfig('.eslintrc.js');
|
||||
spawn(
|
||||
'eslint',
|
||||
[
|
||||
'--config',
|
||||
configFile,
|
||||
'--format',
|
||||
'codeframe',
|
||||
'--ext',
|
||||
'mjs,js',
|
||||
'.',
|
||||
],
|
||||
{
|
||||
env: {
|
||||
NODE_PATH: './node_modules',
|
||||
...process.env,
|
||||
},
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
program
|
||||
.command('lint')
|
||||
.description('run linter')
|
||||
.action(lint);
|
||||
|
||||
const test = async () => {
|
||||
await build(['--display', 'none']);
|
||||
const {production} = program.opts();
|
||||
const configFile = localConfig('.eslintrc.js');
|
||||
spawn(
|
||||
'mocha',
|
||||
[
|
||||
'--colors',
|
||||
'test.js',
|
||||
],
|
||||
{
|
||||
env: {
|
||||
NODE_PATH: './node_modules',
|
||||
...process.env,
|
||||
},
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
program
|
||||
.command('test')
|
||||
.description('build and run tests')
|
||||
.action(test);
|
||||
|
||||
program
|
||||
.option('-d, --no-production', 'dev build');
|
||||
|
||||
program.parse(process.argv);
|
23
packages/build/src/build/.eslint.defaults.js
Normal file
23
packages/build/src/build/.eslint.defaults.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const config = {
|
||||
globals: {
|
||||
__non_webpack_require__: true,
|
||||
process: true,
|
||||
window: true,
|
||||
},
|
||||
ignorePatterns: [
|
||||
'/*',
|
||||
'!/src',
|
||||
],
|
||||
rules: {
|
||||
'babel/object-curly-spacing': 'off',
|
||||
'brace-style': ['error', 'stroustrup'],
|
||||
'no-bitwise': ['error', {int32Hint: true}],
|
||||
'no-plusplus': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'padded-blocks': ['error', {classes: 'always'}],
|
||||
yoda: 'off',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
3
packages/build/src/build/.eslintrc.js
Normal file
3
packages/build/src/build/.eslintrc.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const neutrino = require('neutrino');
|
||||
|
||||
module.exports = neutrino(require(`${__dirname}/.neutrinorc`)).eslintrc();
|
108
packages/build/src/build/.neutrinorc.js
Normal file
108
packages/build/src/build/.neutrinorc.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
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');
|
||||
|
||||
module.exports = {
|
||||
options: {},
|
||||
use: [
|
||||
airbnb({
|
||||
eslint: {
|
||||
cache: false,
|
||||
baseConfig: require(`${__dirname}/.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: process.cwd(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
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'}));
|
||||
},
|
||||
mocha(),
|
||||
],
|
||||
};
|
6
packages/build/src/build/postcss.config.js
Normal file
6
packages/build/src/build/postcss.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* eslint-disable global-require */
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
],
|
||||
};
|
3
packages/build/src/build/webpack.config.js
Normal file
3
packages/build/src/build/webpack.config.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const neutrino = require('neutrino');
|
||||
|
||||
module.exports = neutrino(require(`${__dirname}/.neutrinorc`)).webpack();
|
0
packages/build/src/index.js
Normal file
0
packages/build/src/index.js
Normal file
5
packages/build/test/exists.js
Normal file
5
packages/build/test/exists.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import {expect} from 'chai';
|
||||
|
||||
it('exists', () => {
|
||||
expect(true).to.be.true;
|
||||
});
|
3
packages/build/webpack.config.js
Normal file
3
packages/build/webpack.config.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const neutrino = require('neutrino');
|
||||
|
||||
module.exports = neutrino(require(`${__dirname}/.neutrinorc`)).webpack();
|
4727
packages/build/yarn.lock
Normal file
4727
packages/build/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user