From 95cbf10dd079dc4aaee898230dfc774351be2ed6 Mon Sep 17 00:00:00 2001 From: Braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Sat, 10 Jul 2021 13:54:45 +0200 Subject: [PATCH] update: more changes to bundle config... --- package.json | 16 ++- rollup.config.js | 253 +++++++++++++++++++++++++++++++++++++---------- vite.config.ts | 10 +- 3 files changed, 212 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index 6d6d1492..705bd4dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@braks/revue-flow", - "version": "0.0.20", + "version": "0.0.22", "private": false, "repository": { "type": "git", @@ -8,8 +8,11 @@ }, "license": "MIT", "author": "Burak Cakmakoglu", - "main": "dist/revue-flow.es.js", - "module": "dist/revue-flow.es.js", + "main": "dist/revue-flow.cjs.js", + "browser": "dist/revue-flow.esm.js", + "unpkg": "dist/revue-flow.global.js", + "jsdelivr": "dist/revue-flow.global.js", + "module": "dist/revue-flow.esm-bundler.js", "types": "dist/index.d.ts", "files": [ "dist", @@ -17,11 +20,11 @@ ], "scripts": { "dev": "vite", - "build": "vue-tsc --noEmit && vite build && yarn build:dist", + "build": "vue-tsc --noEmit && vite build", "build:dist": "rollup -c --environment NODE_ENV:production", "build:app": "vite build -c vite.config.app.ts", "serve": "vite preview", - "prepublishOnly": "yarn build", + "prepublishOnly": "yarn build:dist", "test": "exit 0;", "lint:js": "eslint --ext \".js,.jsx,.ts,.tsx\" --fix --ignore-path .gitignore .", "lint": "yarn lint:js" @@ -57,6 +60,7 @@ "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^7.12.1", "np": "^7.5.0", + "pascalcase": "^1.0.0", "postcss": "^8.3.5", "postcss-cli": "^8.3.1", "postcss-nested": "^5.0.5", @@ -66,7 +70,9 @@ "rollup-plugin-livereload": "^2.0.0", "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-serve": "^1.1.0", + "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.30.0", + "rollup-plugin-vue": "^6.0.0", "typescript": "^4.3.5", "vite": "^2.3.8", "vue": "^3.0.5", diff --git a/rollup.config.js b/rollup.config.js index 358f6f57..03421d44 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,66 +1,213 @@ +import path from 'path'; +import ts from 'rollup-plugin-typescript2'; +import replace from '@rollup/plugin-replace'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; -import babel from '@rollup/plugin-babel'; +import pascalcase from 'pascalcase'; +import pkg from './package.json'; import postcss from 'rollup-plugin-postcss'; -import replace from '@rollup/plugin-replace'; -import typescript from 'rollup-plugin-typescript2'; +import babel from '@rollup/plugin-babel'; import { DEFAULT_EXTENSIONS as DEFAULT_BABEL_EXTENSIONS } from '@babel/core'; -import pkg from './package.json'; +const name = pkg.name; -const isProd = process.env.NODE_ENV === 'production'; -const isTesting = process.env.NODE_ENV === 'testing'; -const processEnv = isProd || isTesting ? 'production' : 'development'; +function getAuthors(pkg) { + const { contributors, author } = pkg; -export const baseConfig = ({ injectCSS = true } = {}) => ({ - input: 'src/index.ts', - external: ['vue', 'vue-demi', '@vue/composition-api', (id) => id.includes('@babel/runtime')], - onwarn(warning, rollupWarn) { - if (warning.code !== 'CIRCULAR_DEPENDENCY') { - rollupWarn(warning); - } + const authors = new Set(); + if (contributors && contributors) + contributors.forEach((contributor) => { + authors.add(contributor.name); + }); + if (author) authors.add(author.name); + + return Array.from(authors).join(', '); +} + +const banner = `/*! + * ${pkg.name} v${pkg.version} + * (c) ${new Date().getFullYear()} ${getAuthors(pkg)} + * @license MIT + */`; + +// ensure TS checks only once for each build +let hasTSChecked = false; + +const outputConfigs = { + // each file name has the format: `dist/${name}.${format}.js` + // format being a key of this object + 'esm-bundler': { + file: pkg.module, + format: 'es' }, - output: { - globals: { - vue: 'Vue', - 'vue-demi': 'VueDemi' - }, - dir: 'dist', - sourcemap: true, - exports: 'named' + cjs: { + file: pkg.main, + format: 'cjs' }, - plugins: [ - replace({ - __ENV__: JSON.stringify(processEnv), - __REACT_FLOW_VERSION__: JSON.stringify(pkg.version), - preventAssignment: true - }), - postcss({ - minimize: isProd, - inject: injectCSS - }), - resolve(), - typescript({ - clean: true - }), - commonjs({ - include: 'node_modules/**' - }), - babel({ - extensions: [...DEFAULT_BABEL_EXTENSIONS, '.ts', '.tsx'], - exclude: 'node_modules/**', - babelHelpers: 'inline' - }) - ] + 'global-vue-3': { + file: pkg.unpkg.replace('2', '3'), + format: 'iife' + }, + 'global-vue-2': { + file: pkg.unpkg, + format: 'iife' + }, + esm: { + file: pkg.browser, + format: 'es' + } +}; + +const allFormats = Object.keys(outputConfigs); +const packageFormats = allFormats; +const packageConfigs = packageFormats.map((format) => createConfig(format, outputConfigs[format])); + +// only add the production ready if we are bundling the options +packageFormats.forEach((format) => { + if (format === 'cjs') { + packageConfigs.push(createProductionConfig(format)); + } else if (format.startsWith('global')) { + packageConfigs.push(createMinifiedConfig(format)); + } }); -export default isProd && !isTesting - ? [ - baseConfig(), - baseConfig({ - mainFile: 'dist/nocss/ReactFlow-nocss.js', - moduleFile: 'dist/nocss/ReactFlow-nocss.esm.js', - injectCSS: false +export default packageConfigs; + +function createConfig(format, output, plugins = []) { + if (!output) { + console.log(`invalid format: ${format}`); + process.exit(1); + } + output.exports = 'named'; + output.sourcemap = !!process.env.SOURCE_MAP; + output.banner = banner; + output.externalLiveBindings = false; + output.globals = { vue: 'Vue', 'vue-demi': 'VueDemi' }; + + const isProductionBuild = /\.prod\.js$/.test(output.file); + const isGlobalBuild = format.startsWith('global'); + const isRawESMBuild = format === 'esm'; + const isNodeBuild = format === 'cjs'; + const isBundlerESMBuild = /esm-bundler/.test(format); + + if (isGlobalBuild) output.name = pascalcase(pkg.name); + + const shouldEmitDeclarations = !hasTSChecked; + + const tsPlugin = ts({ + check: !hasTSChecked, + tsconfig: path.resolve(__dirname, 'tsconfig.json'), + cacheRoot: path.resolve(__dirname, 'node_modules/.rts2_cache'), + tsconfigOverride: { + compilerOptions: { + sourceMap: true, + declaration: shouldEmitDeclarations, + declarationMap: shouldEmitDeclarations + }, + exclude: ['__tests__', 'test-dts'] + } + }); + // we only need to check TS and generate declarations once for each build. + // it also seems to run into weird issues when checking multiple times + // during a single build. + hasTSChecked = true; + + const external = ['vue', 'vue-demi', '@vue/composition-api', (id) => id.includes('@babel/runtime')]; + + const nodePlugins = [resolve(), commonjs({ include: 'node_modules/**' })]; + + return { + input: 'src/index.ts', + // Global and Browser ESM builds inlines everything so that they can be + // used alone. + external, + plugins: [ + tsPlugin, + createReplacePlugin( + isProductionBuild, + isBundlerESMBuild, + // isBrowserBuild? + isGlobalBuild || isRawESMBuild || isBundlerESMBuild, + isGlobalBuild, + isNodeBuild + ), + ...nodePlugins, + ...plugins, + postcss({ + minimize: true, + inject: true + }), + babel({ + extensions: [...DEFAULT_BABEL_EXTENSIONS, '.ts', '.tsx'], + exclude: 'node_modules/**', + babelHelpers: 'inline' + }) + ], + output + // onwarn: (msg, warn) => { + // if (!/Circular/.test(msg)) { + // warn(msg) + // } + // }, + }; +} + +function createReplacePlugin(isProduction, isBundlerESMBuild, isBrowserBuild, isGlobalBuild, isNodeBuild) { + const replacements = { + __COMMIT__: `"${process.env.COMMIT}"`, + __VERSION__: `"${pkg.version}"`, + __DEV__: isBundlerESMBuild + ? // preserve to be handled by bundlers + "(process.env.NODE_ENV !== 'production')" + : // hard coded dev/prod builds + !isProduction, + // this is only used during tests + __TEST__: isBundlerESMBuild ? "(process.env.NODE_ENV === 'test')" : false, + // If the build is expected to run directly in the browser (global / esm builds) + __BROWSER__: isBrowserBuild, + // is targeting bundlers? + __BUNDLER__: isBundlerESMBuild, + __GLOBAL__: isGlobalBuild, + // is targeting Node (SSR)? + __NODE_JS__: isNodeBuild, + __ENV__: JSON.stringify(process.env.NODE_ENV), + __REACT_FLOW_VERSION__: JSON.stringify(pkg.version), + preventAssignment: true + }; + // allow inline overrides like + //__RUNTIME_COMPILE__=true yarn build + Object.keys(replacements).forEach((key) => { + if (key in process.env) { + replacements[key] = process.env[key]; + } + }); + return replace(replacements); +} + +function createProductionConfig(format) { + return createConfig(format, { + file: `dist/${name}.${format}.prod.js`, + format: outputConfigs[format].format + }); +} + +function createMinifiedConfig(format) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { terser } = require('rollup-plugin-terser'); + return createConfig( + format, + { + file: `dist/${name}.${format}.prod.js`, + format: outputConfigs[format].format + }, + [ + terser({ + module: /^esm/.test(format), + compress: { + ecma: 2015, + pure_getters: true + } }) ] - : baseConfig(); + ); +} diff --git a/vite.config.ts b/vite.config.ts index 8e086cd9..dde75bf0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -12,14 +12,9 @@ export default defineConfig({ }, sourcemap: true, rollupOptions: { - // make sure to externalize deps that shouldn't be bundled - // into your library - external: ['vue', 'vue-demi', '@vue/composition-api'], + external: ['vue-demi'], output: { - // Provide global variables to use in the UMD build - // for externalized deps globals: { - vue: 'Vue', 'vue-demi': 'VueDemi' }, dir: 'dist', @@ -33,9 +28,6 @@ export default defineConfig({ }, polyfillDynamicImport: true }, - optimizeDeps: { - exclude: ['vue-demi'] - }, plugins: [ vue(), vueJsx({