Skip to content

Commit

Permalink
feat(build): support building for the browser with rollup
Browse files Browse the repository at this point in the history
  • Loading branch information
Kent C. Dodds committed Sep 7, 2017
1 parent 6697b79 commit 25ca58f
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 56 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
{argsIgnorePattern: "^_", varsIgnorePattern: "^ignored"},
],
"no-console": "off",
"no-nested-ternary": "off",
}
}
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,28 @@
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"concurrently": "^3.5.0",
"cross-env": "^5.0.5",
"cross-spawn": "^5.1.0",
"eslint": "^4.2.0",
"eslint-config-kentcdodds": "^12.4.1",
"eslint-config-prettier": "^2.4.0",
"husky": "^0.14.3",
"jest": "^20.0.4",
"lint-staged": "^4.0.1",
"lodash.camelcase": "^4.3.0",
"lodash.has": "^4.5.2",
"lodash.merge": "^4.6.0",
"prettier": "^1.6.1",
"read-pkg-up": "^2.0.0",
"resolve": "^1.4.0",
"rimraf": "^2.6.1"
"rimraf": "^2.6.1",
"rollup": "^0.48.2",
"rollup-plugin-alias": "^1.3.1",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-commonjs": "^8.2.0",
"rollup-plugin-json": "^2.3.0",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-uglify": "^2.0.1",
"rollup-watch": "^4.3.1"
},
"repository": {
"type": "git",
Expand Down
12 changes: 6 additions & 6 deletions src/config/babelrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const {ifAnyDep} = require('../utils')
const {ifAnyDep, parseEnv} = require('../utils')

const isTest = process.env.NODE_ENV === 'test'
const isPreact = process.env.LIBRARY === 'preact'
const isRollup = JSON.parse(process.env.ROLLUP_BUILD || 'false')
const isWebpack = JSON.parse(process.env.WEBPACK_BUILD || 'false')
const treeshake = isRollup || isWebpack
const isPreact = parseEnv('BUILD_PREACT', false)
const isRollup = parseEnv('BUILD_ROLLUP', false)
const isWebpack = parseEnv('BUILD_WEBPACK', false)
const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack)

module.exports = {
presets: [
Expand All @@ -18,7 +18,7 @@ module.exports = {
},
},
],
ifAnyDep('react', require.resolve('babel-preset-react')),
ifAnyDep(['react', 'preact'], require.resolve('babel-preset-react')),
].filter(Boolean),
plugins: [
isRollup ? require.resolve('babel-plugin-external-helpers') : null,
Expand Down
105 changes: 105 additions & 0 deletions src/config/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const path = require('path')
const camelcase = require('lodash.camelcase')
const rollupBabel = require('rollup-plugin-babel')
const commonjs = require('rollup-plugin-commonjs')
const nodeResolve = require('rollup-plugin-node-resolve')
const json = require('rollup-plugin-json')
const uglify = require('rollup-plugin-uglify')
const rollupAlias = require('rollup-plugin-alias')
const {getPkg, hasFile, hasPkgProp, parseEnv} = require('../utils')

const pkg = getPkg()
const here = p => path.join(__dirname, p)

const minify = parseEnv('BUILD_MINIFY', false)
const format = process.env.BUILD_FORMAT
const isPreact = parseEnv('BUILD_PREACT', false)

const capitalize = s => s[0].toUpperCase() + s.slice(1)

const defaultGlobals = Object.keys(pkg.peerDependencies).reduce((deps, dep) => {
deps[dep] = capitalize(camelcase(dep))
return deps
}, {})

const defaultExternal = Object.keys(pkg.peerDependencies)

const filenameSuffix = parseEnv(
'BUILD_FILENAME_SUFFIX',
isPreact ? '.preact' : '',
)
const globals = parseEnv(
'BUILD_GLOBALS',
isPreact ? Object.assign(defaultGlobals, {preact: 'preact'}) : defaultGlobals,
)
const external = parseEnv(
'BUILD_EXTERNAL',
isPreact ? defaultExternal.concat(['preact', 'prop-types']) : defaultExternal,
).filter((e, i, arry) => arry.indexOf(e) === i)

if (isPreact) {
delete globals.react
delete globals['prop-types'] // TODO: is this necessary?
external.splice(external.indexOf('react'), 1)
}

const alias = parseEnv('BUILD_ALIAS', isPreact ? {react: 'preact'} : null)
const esm = format === 'esm'
const umd = format === 'umd'
const cjs = format === 'cjs'

let output

const filename = path.join('dist', pkg.name)

if (esm) {
output = [{file: `${filename}${filenameSuffix}.es.js`, format: 'es'}]
} else if (umd) {
if (minify) {
output = [
{
file: `${filename}${filenameSuffix}.umd.min.js`,
format: 'umd',
sourcemap: true,
},
]
} else {
output = [
{
file: `${filename}${filenameSuffix}.umd.js`,
format: 'umd',
sourcemap: true,
},
]
}
} else if (cjs) {
output = [{file: `${filename}${filenameSuffix}.cjs.js`, format: 'cjs'}]
} else if (format) {
throw new Error(`invalid format specified: "${format}".`)
} else {
throw new Error('no format specified. --environment FORMAT:xxx')
}

const useBuiltinConfig = !hasFile('.babelrc') && !hasPkgProp('babel')
const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []

module.exports = {
input: 'src/index.js',
output,
exports: esm ? 'named' : 'default',
name: capitalize(camelcase(pkg.name)),
external,
globals,
plugins: [
alias ? rollupAlias(alias) : null,
nodeResolve({jsnext: true, main: true}),
commonjs({include: 'node_modules/**'}),
json(),
rollupBabel({
exclude: 'node_modules/**',
presets: babelPresets,
babelrc: true,
}),
minify ? uglify() : null,
].filter(Boolean),
}
Empty file modified src/index.js
100644 → 100755
Empty file.
10 changes: 3 additions & 7 deletions src/scripts/build.js → src/scripts/build/babel.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
const fs = require('fs')
const path = require('path')
const spawn = require('cross-spawn')
const rimraf = require('rimraf')
const {fromRoot} = require('../utils')
const {hasPkgProp, resolveBin} = require('../utils')
const {hasPkgProp, fromRoot, resolveBin, hasFile} = require('../../utils')

const args = process.argv.slice(2)
const here = p => path.join(__dirname, p)

const useBuiltinConfig =
!args.includes('--presets') &&
!fs.existsSync(fromRoot('.babelrc')) &&
!hasPkgProp('babel')
!args.includes('--presets') && !hasFile('.babelrc') && !hasPkgProp('babel')
const config = useBuiltinConfig
? ['--presets', here('../config/babelrc.js')]
? ['--presets', here('../../config/babelrc.js')]
: []

const ignore = args.includes('--ignore')
Expand Down
5 changes: 5 additions & 0 deletions src/scripts/build/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (process.argv.includes('--browser')) {
require('./rollup')
} else {
require('./babel')
}
55 changes: 55 additions & 0 deletions src/scripts/build/rollup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const path = require('path')
const spawn = require('cross-spawn')
const rimraf = require('rimraf')
const {
hasFile,
resolveBin,
fromRoot,
getConcurrentlyArgs,
} = require('../../utils')

const crossEnv = resolveBin('cross-env')
const rollup = resolveBin('rollup')
const args = process.argv.slice(2)
const here = p => path.join(__dirname, p)

const useBuiltinConfig =
!args.includes('--config') && !hasFile('rollup.config.js')
const config = useBuiltinConfig
? `--config ${here('../../config/rollup.config.js')}`
: args.includes('--config') ? '' : '--config' // --config will pick up the rollup.config.js file

const getCommand = env =>
`${crossEnv} BUILD_ROLLUP=true ${env} ${rollup} ${config}`

const scripts = args.includes('--p-react')
? getPReactScripts()
: getConcurrentlyArgs({
esm: getCommand('BUILD_FORMAT=esm'),
cjs: getCommand('BUILD_FORMAT=cjs'),
umd: getCommand('BUILD_FORMAT=umd'),
'umd.min': getCommand('BUILD_FORMAT=umd BUILD_MINIFY=true'),
})

rimraf.sync(fromRoot('dist'))

const result = spawn.sync(resolveBin('concurrently'), scripts, {
stdio: 'inherit',
})

function getPReactScripts() {
return getConcurrentlyArgs({
'react.esm': getCommand('BUILD_FORMAT=esm'),
'react.cjs': getCommand('BUILD_FORMAT=cjs'),
'react.umd': getCommand('BUILD_FORMAT=umd'),
'react.umd.min': getCommand('BUILD_FORMAT=umd BUILD_MINIFY=true'),
'preact.esm': getCommand('BUILD_PREACT=true BUILD_FORMAT=esm'),
'preact.cjs': getCommand('BUILD_PREACT=true BUILD_FORMAT=cjs'),
'preact.umd': getCommand('BUILD_PREACT=true BUILD_FORMAT=umd'),
'preact.umd.min': getCommand(
'BUILD_PREACT=true BUILD_FORMAT=umd BUILD_MINIFY=true',
),
})
}

process.exit(result.status)
8 changes: 3 additions & 5 deletions src/scripts/lint.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
const fs = require('fs')
const path = require('path')
const spawn = require('cross-spawn')
const {fromRoot} = require('../utils')
const {hasPkgProp, resolveBin} = require('../utils')
const {hasPkgProp, resolveBin, hasFile} = require('../utils')

const args = process.argv.slice(2)
const here = p => path.join(__dirname, p)

const useBuiltinConfig =
!args.includes('--config') &&
!fs.existsSync(fromRoot('.eslintrc')) &&
!hasFile('.eslintrc') &&
!hasPkgProp('eslintConfig')
const config = useBuiltinConfig
? ['--config', here('../config/eslintrc.js')]
: []

const useBuiltinIgnore =
!args.includes('--ignore-path') &&
!fs.existsSync(fromRoot('.eslintignore')) &&
!hasFile('.eslintignore') &&
!hasPkgProp('eslintIgnore')

const ignore = useBuiltinIgnore
Expand Down
1 change: 1 addition & 0 deletions src/scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const args = process.argv.slice(2)

const watch =
!process.env.CI &&
!args.includes('--no-watch') &&
!args.includes('--coverage') &&
!args.includes('--updateSnapshot')
? ['--watch']
Expand Down
51 changes: 17 additions & 34 deletions src/scripts/validate.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,29 @@
const spawn = require('cross-spawn')
const {ifScript, resolveBin} = require('../utils')
const {getConcurrentlyArgs, hasScript, resolveBin} = require('../utils')

const validateScripts = process.argv[3]

const scriptNames = (...scripts) =>
scripts
.map(s => ifScript(s, s))
.filter(Boolean)
.join(',')
const validateScripts = process.argv[2]

const useDefaultScripts = typeof validateScripts !== 'string'

const scripts = useDefaultScripts
? [
ifScript('build', 'npm run build --silent'),
ifScript('lint', 'npm run lint --silent'),
ifScript('test', 'npm run test --silent -- --coverage'),
].filter(Boolean)
: validateScripts.split(',').map(npmScript => `npm run ${npmScript} -s`)
const names = useDefaultScripts
? scriptNames('build', 'lint', 'test')
: validateScripts.split(',')

const colors = [
'bgBlue.bold',
'bgGreen.bold',
'bgMagenta.bold',
'black.bgWhite.bold',
'white.bgBlack.bold',
'bgRed.bold',
].join(',')
? Object.entries({
build: 'npm run build --silent',
lint: 'npm run lint --silent',
test: 'npm run test --silent -- --coverage',
}).reduce((scriptsToRun, [name, script]) => {
if (hasScript(name)) {
scriptsToRun[name] = script
}
return scriptsToRun
}, {})
: validateScripts.split(',').reduce((scriptsToRun, name) => {
scriptsToRun[name] = `npm run ${name} --silent`
return scriptsToRun
}, {})

const result = spawn.sync(
resolveBin('concurrently'),
// prettier-ignore
[
'--kill-others-on-fail',
'--prefix', '[{name}]',
'--names', names,
'--prefix-colors', colors,
...scripts,
],
getConcurrentlyArgs(scripts),
{stdio: 'inherit'},
)

Expand Down
Loading

0 comments on commit 25ca58f

Please sign in to comment.