1
0
Fork 0

feat(build): remove rollup, do not bundle the output

BREAKING CHANGE: the library will now be published as loose ES modules.
Library users are better informed on bundling needs, and repeated bundling introduces extra boilerplate code.
This commit is contained in:
Sean Sube 2022-10-08 14:00:11 -05:00
parent 6daf27e498
commit faeff2c645
18 changed files with 219 additions and 1135 deletions

View File

@ -1,16 +0,0 @@
FROM node:17-alpine
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
WORKDIR /app
RUN yarn install --production
COPY . /app
RUN yarn global add file:$(pwd)
ENV PATH="${PATH}:$(yarn global bin)"
ENTRYPOINT [ "node", "/app/out/index.js" ]
CMD [ "--help" ]

View File

@ -1,16 +0,0 @@
FROM node:17-stretch
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
WORKDIR /app
RUN yarn install --production
COPY . /app
RUN yarn global add file:$(pwd)
ENV PATH="${PATH}:$(yarn global bin)"
ENTRYPOINT [ "node", "/app/out/index.js" ]
CMD [ "--help" ]

169
Makefile
View File

@ -1,170 +1 @@
# Git
export GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
export GIT_COMMIT ?= $(shell git rev-parse HEAD)
export GIT_OPTIONS ?=
export GIT_REMOTES ?= $(shell git remote -v | awk '{ print $1; }' | sort | uniq)
export GIT_TAG ?= $(shell git tag -l --points-at HEAD | head -1)
# Paths
# resolve the makefile's path and directory, from https://stackoverflow.com/a/18137056
export MAKE_PATH ?= $(abspath $(lastword $(MAKEFILE_LIST)))
export ROOT_PATH ?= $(dir $(MAKE_PATH))
export CONFIG_PATH ?= $(ROOT_PATH)/config
export DOCS_PATH ?= $(ROOT_PATH)/docs
export SCRIPT_PATH ?= $(ROOT_PATH)/scripts
export SOURCE_PATH ?= $(ROOT_PATH)/src
export TARGET_PATH ?= $(ROOT_PATH)/out
export TARGET_LOG ?= $(TARGET_PATH)/make.log
export TARGET_MAIN ?= $(TARGET_PATH)/index.js
export TEST_PATH ?= $(ROOT_PATH)/test
export VENDOR_PATH ?= $(ROOT_PATH)/vendor
# CI
export CI_COMMIT_REF_SLUG ?= $(GIT_BRANCH)
export CI_COMMIT_SHA ?= $(GIT_COMMIT)
export CI_COMMIT_TAG ?= $(GIT_TAG)
export CI_ENVIRONMENT_SLUG ?= local
export CI_JOB_ID ?= 0
export CI_PROJECT_PATH ?= $(shell ROOT_PATH=$(ROOT_PATH) ${SCRIPT_PATH}/ci-project-path.sh)
export CI_RUNNER_DESCRIPTION ?= $(shell hostname)
export CI_RUNNER_ID ?= $(shell hostname)
export CI_RUNNER_VERSION ?= 0.0.0
# Debug
export DEBUG_BIND ?= 127.0.0.1
export DEBUG_PORT ?= 9229
# Versions
export NODE_VERSION := $(shell node -v || echo "none")
export RUNNER_VERSION := $(CI_RUNNER_VERSION)
# Node options
NODE_BIN := $(ROOT_PATH)/node_modules/.bin
NODE_CMD ?= $(shell env node)
NODE_DEBUG ?= --inspect-brk=$(DEBUG_BIND):$(DEBUG_PORT) --nolazy
NODE_INFO := $(shell node -v)
# Tool options
COVER_OPTS ?= --reporter=lcov --reporter=text-summary --reporter=html --report-dir="$(TARGET_PATH)/coverage" --exclude-after-remap
MOCHA_OPTS ?= --check-leaks --colors --sort --ui bdd
RELEASE_OPTS ?= --commit-all
.PHONY: all clean clean-deps clean-target configure help todo
.PHONY: build build-bundle build-docs build-image test test-check test-cover test-watch
.PHONY: yarn-install yarn-upgrade git-push git-stats license-check release release-dry upload-climate upload-codecov
all: build test ## builds, bundles, and tests the application
@echo Success!
clean: ## clean up everything added by the default target
clean: clean-deps clean-target
clean-deps: ## clean up the node_modules directory
rm -rf node_modules
clean-target: ## clean up the target directory
rm -rf $(TARGET_PATH)
configure: ## create the target directory and other files not in git
mkdir -p $(TARGET_PATH)
node_modules: yarn-install
# from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help: ## print this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort \
| sed 's/^.*\/\(.*\)/\1/' \
| awk 'BEGIN {FS = ":[^:]*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
todo:
@echo "Remaining tasks:"
@echo ""
@grep -i "todo" -r docs/ src/ test/ || true
@echo ""
@echo "Pending tests:"
@echo ""
@grep "[[:space:]]xit" -r test/ || true
@echo "Casts to any:"
@echo ""
@grep "as any" -r src/ test/ || true
@echo ""
# Build targets
build: ## builds, bundles, and tests the application
build: build-bundle build-docs
build-bundle: node_modules
$(NODE_BIN)/rollup --config $(CONFIG_PATH)/rollup.js
sed -i '1s;^;#! /usr/bin/env node\n\n;' $(TARGET_PATH)/index.js
build-docs: ## generate html docs
$(NODE_BIN)/api-extractor run --config $(CONFIG_PATH)/api-extractor.json --local -v
$(NODE_BIN)/api-documenter markdown -i $(TARGET_PATH)/api -o $(DOCS_PATH)/api
build-image: ## build a docker image
$(SCRIPT_PATH)/docker-build.sh --push
test: ## run mocha unit tests
test: test-cover
test-check: ## run mocha unit tests with coverage reports
$(NODE_BIN)/c8 $(COVER_OPTS) \
$(NODE_BIN)/mocha $(MOCHA_OPTS) \
$(TARGET_PATH)/test.js
test-cover: ## run mocha unit tests with coverage reports
test-cover: test-check
sed -i $(TARGET_PATH)/coverage/lcov.info \
-e '/external ".*"$$/,/end_of_record/d' \
-e '/ sync$$/,/end_of_record/d' \
-e '/test sync/,/end_of_record/d' \
-e '/node_modules/,/end_of_record/d' \
-e '/bootstrap$$/,/end_of_record/d' \
-e '/universalModuleDefinition/,/end_of_record/d'
sed -n '/^SF/,$$p' -i $(TARGET_PATH)/coverage/lcov.info
sed '1s;^;TN:\n;' -i $(TARGET_PATH)/coverage/lcov.info
test-watch:
$(NODE_BIN)/c8 $(COVER_OPTS) $(NODE_BIN)/mocha $(MOCHA_OPTS) --watch $(TARGET_PATH)/test-bundle.js
yarn-install: ## install dependencies from package and lock file
yarn
yarn-global: ## install bundle as a global tool
yarn global add file:$(ROOT_PATH)
yarn-update: ## check yarn for outdated packages
yarn upgrade-interactive --latest
# release targets
git-push: ## push to both gitlab and github (this assumes you have both remotes set up)
git push $(GIT_OPTIONS) github $(GIT_BRANCH)
git push $(GIT_OPTIONS) gitlab $(GIT_BRANCH)
# from https://gist.github.com/amitchhajer/4461043#gistcomment-2349917
git-stats: ## print git contributor line counts (approx, for fun)
git ls-files | while read f; do git blame -w -M -C -C --line-porcelain "$$f" |\
grep -I '^author '; done | sort -f | uniq -ic | sort -n
license-check: ## check license status
licensed cache
licensed status
RELEASE_OPTS ?= --sign
release: ## create a release
$(NODE_BIN)/standard-version $(RELEASE_OPTS)
GIT_OPTIONS=--tags $(MAKE) git-push
release-dry: ## test creating a release
$(NODE_BIN)/standard-version $(RELEASE_OPTS) --dry-run
upload-climate:
cc-test-reporter format-coverage -t lcov -o $(TARGET_PATH)/coverage/codeclimate.json -p $(ROOT_PATH) $(TARGET_PATH)/coverage/lcov.info
cc-test-reporter upload-coverage --debug -i $(TARGET_PATH)/coverage/codeclimate.json -r "$(shell echo "${CODECLIMATE_SECRET}" | base64 -d)"
upload-codecov:
codecov --disable=gcov --file=$(TARGET_PATH)/coverage/lcov.info --token=$(shell echo "${CODECOV_SECRET}" | base64 -d)
include $(shell find $(ROOT_PATH) -name '*.mk' | grep -v node_modules)

92
config/common.mk Normal file
View File

@ -0,0 +1,92 @@
SHELL := bash
# Git
export GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
export GIT_COMMIT ?= $(shell git rev-parse HEAD)
export GIT_OPTIONS ?=
export GIT_REMOTES ?= $(shell git remote -v | awk '{ print $1; }' | sort | uniq)
export GIT_TAG ?= $(shell git tag -l --points-at HEAD | head -1)
# Paths
# resolve the makefile's path and directory, from https://stackoverflow.com/a/18137056
export MAKE_PATH ?= $(abspath $(firstword $(MAKEFILE_LIST)))
export ROOT_PATH ?= $(dir $(MAKE_PATH))
export CONFIG_PATH ?= $(ROOT_PATH)/config
export DOCS_PATH ?= $(ROOT_PATH)/docs
export SCRIPT_PATH ?= $(ROOT_PATH)/scripts
export SOURCE_PATH ?= $(ROOT_PATH)/src
export TARGET_PATH ?= $(ROOT_PATH)/out
export TARGET_LOG ?= $(TARGET_PATH)/make.log
export TARGET_MAIN ?= $(TARGET_PATH)/index.js
export TEST_PATH ?= $(ROOT_PATH)/test
export VENDOR_PATH ?= $(ROOT_PATH)/vendor
# CI
export CI_COMMIT_REF_SLUG ?= $(GIT_BRANCH)
export CI_COMMIT_SHA ?= $(GIT_COMMIT)
export CI_COMMIT_TAG ?= $(GIT_TAG)
export CI_ENVIRONMENT_SLUG ?= local
export CI_JOB_ID ?= 0
export CI_PROJECT_PATH ?= $(shell ROOT_PATH=$(ROOT_PATH) ${SCRIPT_PATH}/ci-project-path.sh)
export CI_RUNNER_DESCRIPTION ?= $(shell hostname)
export CI_RUNNER_ID ?= $(shell hostname)
export CI_RUNNER_VERSION ?= 0.0.0
.PHONY: all ci clean clean-target configure help release release-dry todo
# Targets that must be provided by other files: bundle, build, cover, docs, clean-deps
all: lint build cover docs ## builds, bundles, and tests the application
@echo Success!
clean: ## clean up everything added by the default target
clean: clean-deps clean-target
clean-target: ## clean up the target directory
rm -rf out/
configure: ## create the target directory and other files not in git
mkdir -p $(TARGET_PATH)
# from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
help: ## print this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort \
| sed 's/^.*\/\(.*\)/\1/' \
| awk 'BEGIN {FS = ":[^:]*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
RELEASE_ARGS ?= --commit-all --sign
release: ## tag and push a release
release: node_modules
if [[ "$(GIT_BRANCH)" != master ]]; \
then \
echo "Please merge to master before releasing."; \
exit 1; \
fi
yarn standard-version $(RELEASE_ARGS)
GIT_ARGS=--follow-tags $(MAKE) push
release-dry: ## test creating a release
RELEASE_ARGS="$(RELEASE_ARGS) --dry-run" make release
todo:
@echo "Remaining tasks:"
@echo ""
@grep -i "todo" -r docs/ src/ test/ || true
@echo ""
@echo "Pending tests:"
@echo ""
@grep "[[:space:]]xit" -r test/ || true
@echo ""
@echo "Casts to any:"
@echo ""
@grep "as any" -r src/ test/ || true
@echo ""
@echo "Uses of null:"
@echo ""
@grep -P -e "null(?!able)" -r src/ test/ || true
@echo ""
@echo "Uses of ==:"
@echo ""
@grep -e "[^=!]==[^=]" -r src/ test/ || true
@echo ""

12
config/git.mk Normal file
View File

@ -0,0 +1,12 @@
.PHONY: push git-stats git-push
push: git-push
# from https://gist.github.com/amitchhajer/4461043#gistcomment-2349917
git-stats: ## print git contributor line counts (approx, for fun)
git ls-files | while read f; do git blame -w -M -C -C --line-porcelain "$$f" |\
grep -I '^author '; done | sort -f | uniq -ic | sort -n
git-push: ## push to both github and gitlab
git push $(GIT_ARGS) github $(GIT_BRANCH)
git push $(GIT_ARGS) gitlab $(GIT_BRANCH)

73
config/node.mk Normal file
View File

@ -0,0 +1,73 @@
export NODE_VERSION := $(shell node -v 2>/dev/null || echo "none")
export PACKAGE_NAME := $(shell jq -r '.name' package.json 2>/dev/null || echo "unknown")
export PACKAGE_VERSION := $(shell jq -r '.version' package.json 2>/dev/null || echo "unknown")
export RUNNER_VERSION := $(CI_RUNNER_VERSION)
# Debug
export DEBUG_BIND ?= 127.0.0.1
export DEBUG_PORT ?= 9229
# Node options
NODE_CMD ?= $(shell env node)
NODE_DEBUG ?= --inspect-brk=$(DEBUG_BIND):$(DEBUG_PORT) --nolazy
.PHONY: build ci clean-deps cover deps docs lint test yarn-global yarn-upgrade
# directory targets
node_modules: deps
out: build
# phony targets
build: ## build the app
build: node_modules
yarn tsc
cat $(TARGET_PATH)/src/version.js | envsubst > $(TARGET_PATH)/src/version-out.js
mv $(TARGET_PATH)/src/version-out.js $(TARGET_PATH)/src/version.js
ci: clean-target lint build cover docs
clean-deps: ## clean up the node_modules directory
rm -rf node_modules/
COVER_ARGS := --all \
--check-coverage \
--exclude ".eslintrc.js" \
--exclude "config/**" \
--exclude "docs/**" \
--exclude "examples/**" \
--exclude "out/coverage/**" \
--exclude "vendor/**" \
--reporter=text-summary \
--reporter=lcov \
--report-dir=out/coverage
cover: ## run tests with coverage
cover: node_modules out
yarn c8 $(COVER_ARGS) yarn mocha $(MOCHA_ARGS) "out/**/Test*.js"
deps:
yarn
docs:
yarn api-extractor run -c config/api-extractor.json
yarn api-documenter markdown -i out/api -o docs/api
lint: ## run eslint
lint: node_modules
yarn eslint src/ --ext .ts,.tsx
MOCHA_ARGS := --async-only \
--check-leaks \
--forbid-only \
--require source-map-support/register \
--require out/test/setup.js \
--recursive \
--sort
test: ## run tests
test: node_modules out
yarn mocha $(MOCHA_ARGS) "out/**/Test*.js"
yarn-upgrade: ## check yarn for potential upgrades
yarn upgrade-interactive --latest

View File

@ -1,12 +0,0 @@
{
"names": [
"chai",
"fs",
"mock-fs",
"module",
"process",
"sinon",
"source-map",
"source-map-support"
]
}

View File

@ -1 +0,0 @@
{}

View File

@ -1,6 +0,0 @@
{
"node_modules/chai/index.js": [
"expect",
"use"
]
}

View File

@ -1,3 +0,0 @@
{
"names": []
}

View File

@ -1,127 +0,0 @@
import { join, sep } from 'path';
import commonjs from 'rollup-plugin-commonjs';
import { eslint } from 'rollup-plugin-eslint';
import json from 'rollup-plugin-json';
import multiEntry from 'rollup-plugin-multi-entry';
import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import typescript from 'rollup-plugin-typescript2';
import yaml from 'rollup-plugin-yaml';
const flag_debug = process.env['DEBUG'] === 'TRUE';
const metadata = require('../package.json');
const external = require('./rollup-external.json').names;
const namedExports = require('./rollup-named.json');
const rootPath = process.env['ROOT_PATH'];
const targetPath = process.env['TARGET_PATH'];
const bundle = {
external,
input: {
include: [
join(rootPath, 'src', 'index.ts'),
join(rootPath, 'test', 'harness.ts'),
join(rootPath, 'test', '**', 'Test*.ts'),
],
},
manualChunks(id) {
if (id.includes(`${sep}test${sep}`)) {
return 'test';
}
if (id.match(/commonjs-external/i) || id.match(/commonjsHelpers/)) {
return 'vendor';
}
if (id.match(/node-resolve:/)) {
return 'vendor';
}
if (id.includes(`chai`) || id.includes(`sinon`) || id.includes('source-map')) {
return 'test';
}
if (id.includes(`${sep}node_modules${sep}`)) {
return 'vendor';
}
if (id.includes(`${sep}src${sep}index`)) {
return 'index';
}
if (id.includes(`${sep}src${sep}`) || id.includes(`${sep}rules${sep}`)) {
return 'main';
}
if (id.includes(process.env['HOME'])) {
return 'linked';
}
if (id.length === 30 && id.match(/^[a-f0-9]+$/)) {
return 'vendor';
}
if (flag_debug) {
console.log('file does not belong to any chunk:', id);
}
return 'nochunk';
},
output: {
dir: targetPath,
chunkFileNames: '[name].js',
entryFileNames: 'entry-[name].js',
exports: 'named',
format: 'module',
minifyInternalExports: false,
sourcemap: true,
},
plugins: [
multiEntry(),
json(),
yaml(),
replace({
delimiters: ['{{ ', ' }}'],
values: {
BUILD_JOB: process.env['CI_JOB_ID'],
BUILD_RUNNER: process.env['CI_RUNNER_DESCRIPTION'],
GIT_BRANCH: process.env['CI_COMMIT_REF_SLUG'],
GIT_COMMIT: process.env['CI_COMMIT_SHA'],
NODE_VERSION: process.env['NODE_VERSION'],
PACKAGE_NAME: metadata.name,
PACKAGE_VERSION: metadata.version,
},
}),
resolve({
preferBuiltins: true,
}),
commonjs({
namedExports,
}),
eslint({
exclude: [
join('node_modules', '**'),
join('src', 'resource'),
join('src', '**', '*.json'),
join('src', '**', '*.yml'),
],
include: [
join('src', '**', '*.ts'),
join('test', '**', '*.ts'),
],
throwOnError: true,
useEslintrc: true,
}),
typescript({
cacheRoot: join(targetPath, 'cache', 'rts2'),
rollupCommonJSResolveHack: true,
}),
],
};
export default [
bundle,
];

View File

@ -52,16 +52,6 @@
"mocha-foam": "0.1.8",
"mock-fs": "5.1.4",
"noicejs": "4.0.0",
"rollup": "2.79.1",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-eslint": "7.0.0",
"rollup-plugin-json": "4.0.0",
"rollup-plugin-multi-entry": "2.1.0",
"rollup-plugin-node-externals": "4.1.1",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-replace": "2.2.0",
"rollup-plugin-typescript2": "0.34.0",
"rollup-plugin-yaml": "2.0.0",
"sinon": "14.0.1",
"sinon-chai": "3.7.0",
"source-map-support": "0.5.21",

View File

@ -58,20 +58,6 @@
"schedule:daily"
],
"groupName": "eslint-plugins"
},
{
"matchPackagePatterns": [
"rollup",
"rollup-plugin-.+",
"@rollup/plugin-.+"
],
"matchPackagePrefixes": [
"@rollup"
],
"extends": [
"schedule:earlyMondays"
],
"groupName": "rollup-plugins"
}
]
}

1
run.mk
View File

@ -1 +0,0 @@
ci: all

20
test/setup.ts Normal file
View File

@ -0,0 +1,20 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import sinonChai from 'sinon-chai';
export function setupTests(): void {
/**
* This will break the whole test run if any test leaks an unhandled rejection.
*/
process.on('unhandledRejection', (reason, promise) => {
/* c8 ignore next 3 */
// eslint-disable-next-line no-console
console.error('unhandled error during tests', reason);
process.exit(1);
});
chai.use(chaiAsPromised);
chai.use(sinonChai);
}
setupTests();

782
yarn.lock

File diff suppressed because it is too large Load Diff