fliphub-monorepo
Version:
the builder of builders
174 lines (142 loc) • 5.02 kB
JavaScript
const {join, isAbsolute} = require('path')
const {EventEmitter} = require('events')
const DevServer = require('webpack-dev-server')
const webpack = require('webpack')
const Config = require('flip-webpack-chain')
const ora = require('ora')
const merge = require('deepmerge')
const {defaultTo} = require('ramda')
const timer = require('fliptime')
const log = require('fliplog')
const requireMiddleware = require('./requirePreset')
const normalizePath = (path, root) => (isAbsolute(path) ? path : join(root, path))
class Neutrino extends EventEmitter {
constructor(options = {}) {
super()
this.version = 5.1
const root = normalizePath(options.root || '', process.cwd())
const source = normalizePath(options.source || 'src', root)
const output = normalizePath(options.output || 'build', root)
const tests = normalizePath(options.tests || 'test', root)
const node_modules = normalizePath(options.node_modules || 'node_modules', root) // eslint-disable-line camelcase
const entry = normalizePath(options.entry || 'index.js', source)
this.config = new Config()
this.options = merge(options, {root, source, output, tests, node_modules, entry})
}
use(middleware, options = {}) {
middleware(this, options)
}
import(middleware) {
this.require(middleware).forEach((middleware) => this.use(middleware))
}
require(middleware) {
return requireMiddleware(middleware, this.options)
}
handleErrors(err, stats) {
if (err) {
console.error(err.stack || err)
if (err.details) {
console.error(err.details)
}
return true
}
const jsonStats = stats.toJson()
if (jsonStats.errors.length) {
jsonStats.errors.map((err) => console.error(err))
return true
}
return false
}
getWebpackOptions() {
const config = this.config.toConfig()
// delete config.resolve.modules
return config
}
emitForAll(eventName, payload) {
return Promise.all(this.listeners(eventName).map((fn) => fn(payload)))
}
build(args) {
return this.builder()
return this.runCommand('build', args, () => this.builder())
}
start(args) {
return this.runCommand('start', args, () => (this.getWebpackOptions().devServer ? this.devServer() : this.watcher()))
}
test(args) {
return this.runCommand('test', args)
}
runCommand(command, args = {}, fn) {
process.env.NODE_ENV = defaultTo({
build: 'production',
start: 'development',
test: 'test',
}[command], args.env)
return this
.emitForAll(`pre${command}`, args)
.then(fn)
.then(() => this.emitForAll(command, args))
}
devServer() {
return new Promise((resolve) => {
const starting = ora('Starting development server').start()
const config = this.getWebpackOptions()
const protocol = config.devServer.https ? 'https' : 'http'
const host = config.devServer.host || 'localhost'
const port = config.devServer.port || 5000
config.devServer.noInfo = true
const compiler = webpack(config)
const server = new DevServer(compiler, config.devServer)
const building = ora('Waiting for initial build to finish').start()
process.on('SIGINT', resolve)
server.listen(port, host, () => {
starting.succeed(`Development server running on: ${protocol}://${host}:${port}`)
compiler.plugin('compile', () => {
building.text = 'Source changed, re-compiling'
building.start()
})
compiler.plugin('done', () => building.succeed('Build completed'))
})
})
}
watcher() {
return new Promise((resolve) => {
const building = ora('Waiting for initial build to finish').start()
const config = this.getWebpackOptions()
const compiler = webpack(config)
const watcher = compiler.watch(config.watchOptions || {}, (err, stats) => {
building.succeed('Build completed')
this.handleErrors(err, stats)
})
process.on('SIGINT', () => watcher.close(resolve))
})
}
builder() {
return new Promise((resolve, reject) => {
const config = this.config.toConfig()
// delete config.module
// delete config.resolve.modules
// delete config.entry.index
// delete config.context
timer.start('webpack')
// log.quick(this.config.module.rules)
// log.quick(this.config.module.entries())
// log.quick(this.config, config)
const compiler = webpack(config)
// eslint-disable-next-line consistent-return
compiler.run((err, stats) => {
const failed = this.handleErrors(err, stats)
if (failed) return reject(err)
// eslint-disable-next-line no-console
console.log(stats.toString({
colors: true,
chunks: false,
children: false,
}))
timer.stop('webpack').log('webpack')
resolve()
})
})
}
}
Neutrino.requireMiddleware = requireMiddleware
module.exports = Neutrino