bunchee 4.2.0 → 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # bunchee
2
2
 
3
- > zero config bundler for JavaScript/TypeScript/JSX library
3
+ > Zero-config bundler for frontend libraries.
4
4
 
5
5
  ![bunchee](https://repository-images.githubusercontent.com/154026156/5d132698-0ff5-4644-a4fd-d9570e6229bc)
6
6
 
@@ -15,6 +15,7 @@
15
15
  </p>
16
16
 
17
17
  Bunchee makes bundling your library into one file effortless, with zero configuration required. It is built on top of Rollup and SWC ⚡️, allowing you to focus on writing code and generating multiple module types (CommonJS, ESModules) simultaneously.
18
+ It uses the standard exports configuration in `package.json` as the only source of truth, and uses entry file conventions to match your exports and build them into bundles.
18
19
 
19
20
  ## Quick Start
20
21
 
package/dist/bin/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  var path = require('path');
3
3
  var arg = require('arg');
4
4
  var fs = require('fs/promises');
5
+ var bunchee = require('bunchee');
5
6
 
6
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
8
 
@@ -54,7 +55,7 @@ async function fileExists(filePath) {
54
55
  }
55
56
  }
56
57
 
57
- var version = "4.2.0";
58
+ var version = "4.2.2";
58
59
 
59
60
  const helpMessage = `
60
61
  Usage: bunchee [options]
@@ -165,11 +166,10 @@ async function run(args) {
165
166
  return help();
166
167
  }
167
168
  const entry = source ? path__default.default.resolve(cwd, source) : '';
168
- const bundle = require('../index').bundle;
169
169
  let timeStart = Date.now();
170
170
  let timeEnd;
171
171
  try {
172
- await bundle(entry, bundleConfig);
172
+ await bunchee.bundle(entry, bundleConfig);
173
173
  timeEnd = Date.now();
174
174
  } catch (err) {
175
175
  if (err.name === 'NOT_EXISTED') {
package/dist/index.js CHANGED
@@ -591,6 +591,12 @@ function getBuildEnv(envs) {
591
591
  }
592
592
  async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPath, tsCompilerOptions }, pluginContext, dts) {
593
593
  const entriesAlias = getEntriesAlias(entries);
594
+ const reversedAlias = {};
595
+ for (const [key, value] of Object.entries(entriesAlias)){
596
+ if (value !== entry) {
597
+ reversedAlias[value] = key;
598
+ }
599
+ }
594
600
  const hasNoExternal = options.external === null;
595
601
  var _options_external;
596
602
  const externals = hasNoExternal ? [] : [
@@ -631,12 +637,6 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
631
637
  isModule: true
632
638
  };
633
639
  const sizePlugin = pluginContext.sizeCollector.plugin(cwd);
634
- const reversedAlias = {};
635
- for (const [key, value] of Object.entries(entriesAlias)){
636
- if (value !== entry) {
637
- reversedAlias[value] = key;
638
- }
639
- }
640
640
  // common plugins for both dts and ts assets that need to be processed
641
641
  const commonPlugins = [
642
642
  sizePlugin,
@@ -659,7 +659,7 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
659
659
  tsBuildInfoFile: '.tsbuildinfo',
660
660
  target: 'esnext',
661
661
  module: 'esnext',
662
- jsx: tsCompilerOptions.jsx || 'react'
662
+ jsx: tsCompilerOptions.jsx || 'react-jsx'
663
663
  };
664
664
  const typesPlugins = [
665
665
  ...commonPlugins,
@@ -732,7 +732,8 @@ async function buildInputConfig(entry, entries, pkg, options, cwd, { tsConfigPat
732
732
  'MIXED_EXPORTS',
733
733
  'PREFER_NAMED_EXPORTS',
734
734
  'UNRESOLVED_IMPORT',
735
- 'THIS_IS_UNDEFINED'
735
+ 'THIS_IS_UNDEFINED',
736
+ 'INVALID_ANNOTATION'
736
737
  ].includes(code)) return;
737
738
  // If the circular dependency warning is from node_modules, ignore it
738
739
  if (code === 'CIRCULAR_DEPENDENCY' && /Circular dependency: node_modules/.test(warning.message)) {
@@ -754,26 +755,58 @@ function hasEsmExport(exportPaths, tsCompilerOptions) {
754
755
  }
755
756
  return Boolean(hasEsm || (tsCompilerOptions == null ? void 0 : tsCompilerOptions.esModuleInterop));
756
757
  }
757
- const splitChunks = (id, ctx)=>{
758
- const moduleInfo = ctx.getModuleInfo(id);
759
- if (!moduleInfo) {
760
- return;
761
- }
762
- const moduleMeta = moduleInfo.meta;
763
- if (!moduleMeta) {
764
- return;
765
- }
758
+ function getModuleLater(moduleMeta) {
766
759
  const directives = (moduleMeta.preserveDirectives || {
767
760
  directives: []
768
761
  }).directives.map((d)=>d.replace(/^use /, '')).filter((d)=>d !== 'strict');
769
762
  const moduleLayer = directives[0];
770
- if (moduleLayer && !moduleMeta.isEntry) {
771
- const chunkName = path__default.default.basename(id, path__default.default.extname(id));
772
- return `${chunkName}-${moduleLayer}`;
773
- }
774
- return;
775
- };
776
- function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { tsCompilerOptions }, dts) {
763
+ return moduleLayer;
764
+ }
765
+ // dependencyGraphMap: Map<subModuleId, Set<entryParentId>>
766
+ function createSplitChunks(dependencyGraphMap) {
767
+ return function splitChunks(id, ctx) {
768
+ const moduleInfo = ctx.getModuleInfo(id);
769
+ if (!moduleInfo) {
770
+ return;
771
+ }
772
+ const { isEntry } = moduleInfo;
773
+ const moduleMeta = moduleInfo.meta;
774
+ const moduleLayer = getModuleLater(moduleMeta);
775
+ // Collect the sub modules of the entry, if they're having layer, and the same layer with the entry, push them to the dependencyGraphMap.
776
+ if (isEntry) {
777
+ const subModuleIds = ctx.getModuleIds();
778
+ for (const subId of subModuleIds){
779
+ const subModuleInfo = ctx.getModuleInfo(subId);
780
+ if (!subModuleInfo) {
781
+ continue;
782
+ }
783
+ const subModuleLayer = getModuleLater(moduleMeta);
784
+ if (subModuleLayer === moduleLayer) {
785
+ if (!dependencyGraphMap.has(subId)) {
786
+ dependencyGraphMap.set(subId, new Set());
787
+ }
788
+ dependencyGraphMap.get(subId).add(id);
789
+ }
790
+ }
791
+ }
792
+ // If current module has a layer, and it's not an entry
793
+ if (moduleLayer && !isEntry) {
794
+ // If the module is imported by the entry:
795
+ // when the module layer is same as entry layer, keep it as part of entry and don't split it;
796
+ // when the module layer is different from entry layer, split the module into a separate chunk as a separate boundary.
797
+ if (dependencyGraphMap.has(id)) {
798
+ const parentModuleLayers = Array.from(dependencyGraphMap.get(id));
799
+ if (parentModuleLayers.every((layer)=>layer === moduleLayer)) {
800
+ return;
801
+ }
802
+ const chunkName = path__default.default.basename(id, path__default.default.extname(id));
803
+ return `${chunkName}-${moduleLayer}`;
804
+ }
805
+ }
806
+ return;
807
+ };
808
+ }
809
+ function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { tsCompilerOptions }, pluginContext, dts) {
777
810
  const { format } = options;
778
811
  // Add esm mark and interop helper if esm export is detected
779
812
  const useEsModuleMark = hasEsmExport(exportPaths, tsCompilerOptions);
@@ -799,7 +832,7 @@ function buildOutputConfigs(pkg, exportPaths, options, exportCondition, cwd, { t
799
832
  freeze: false,
800
833
  strict: false,
801
834
  sourcemap: options.sourcemap,
802
- manualChunks: splitChunks,
835
+ manualChunks: createSplitChunks(pluginContext.moduleDirectiveLayerMap),
803
836
  chunkFileNames: '[name]-[hash].js',
804
837
  // By default in rollup, when creating multiple chunks, transitive imports of entry chunks
805
838
  // will be added as empty imports to the entry chunks. Disable to avoid imports hoist outside of boundaries
@@ -911,18 +944,19 @@ async function buildConfig(entries, pkg, exportPaths, bundleConfig, exportCondit
911
944
  ...bundleConfig,
912
945
  useTypescript
913
946
  };
914
- const inputOptions = await buildInputConfig(exportCondition.source, entries, pkg, options, cwd, tsOptions, pluginContext, dts);
947
+ const entry = exportCondition.source;
948
+ const inputOptions = await buildInputConfig(entry, entries, pkg, options, cwd, tsOptions, pluginContext, dts);
915
949
  const outputExports = getExportConditionDist(pkg, exportCondition, cwd);
916
950
  let outputConfigs = [];
917
951
  // Generate dts job - single config
918
952
  if (dts) {
919
953
  const typeOutputExports = getExportTypeDist(exportCondition, cwd);
920
- outputConfigs = typeOutputExports.map((v)=>buildOutputConfigs(pkg, exportPaths, {
954
+ outputConfigs = typeOutputExports.map((typeFile)=>buildOutputConfigs(pkg, exportPaths, {
921
955
  ...bundleConfig,
922
956
  format: 'es',
923
957
  useTypescript,
924
- file: v
925
- }, exportCondition, cwd, tsOptions, dts));
958
+ file: typeFile
959
+ }, exportCondition, cwd, tsOptions, pluginContext, dts));
926
960
  } else {
927
961
  // multi outputs with specified format
928
962
  outputConfigs = outputExports.map((exportDist)=>{
@@ -931,7 +965,7 @@ async function buildConfig(entries, pkg, exportPaths, bundleConfig, exportCondit
931
965
  file: exportDist.file,
932
966
  format: exportDist.format,
933
967
  useTypescript
934
- }, exportCondition, cwd, tsOptions, dts);
968
+ }, exportCondition, cwd, tsOptions, pluginContext, dts);
935
969
  });
936
970
  // CLI output option is always prioritized
937
971
  if (file) {
@@ -943,7 +977,7 @@ async function buildConfig(entries, pkg, exportPaths, bundleConfig, exportCondit
943
977
  file,
944
978
  format: bundleConfig.format || fallbackFormat,
945
979
  useTypescript
946
- }, exportCondition, cwd, tsOptions, dts)
980
+ }, exportCondition, cwd, tsOptions, pluginContext, dts)
947
981
  ];
948
982
  }
949
983
  }
@@ -977,24 +1011,23 @@ function createChunkSizeCollector({ entries }) {
977
1011
  plugin: (cwd)=>{
978
1012
  return {
979
1013
  name: 'collect-sizes',
980
- augmentChunkHash () {
981
- // Do nothing, but use the hook to keep the plugin instance alive
982
- },
983
- renderChunk (code, chunk, options) {
984
- const sourceId = chunk.facadeModuleId || '';
985
- const dir = options.dir || options.file && path__default.default.dirname(options.file);
986
- let fileName = chunk.fileName;
987
- if (dir) {
1014
+ writeBundle (options, bundle) {
1015
+ const dir = options.dir || path__default.default.dirname(options.file);
1016
+ Object.entries(bundle).forEach(([fileName, chunk])=>{
988
1017
  const filePath = path__default.default.join(dir, fileName);
989
- fileName = filePath.startsWith(cwd) ? path__default.default.relative(cwd, filePath) : filePath;
990
- }
991
- addSize({
992
- fileName,
993
- size: code.length,
994
- sourceFileName: sourceId,
995
- exportPath: reversedMapping.get(sourceId) || '.'
1018
+ if (chunk.type !== 'chunk') {
1019
+ return;
1020
+ }
1021
+ const size = chunk.code.length;
1022
+ const sourceFileName = chunk.facadeModuleId || '';
1023
+ const exportPath = reversedMapping.get(sourceFileName) || '.';
1024
+ addSize({
1025
+ fileName: filePath.startsWith(cwd) ? path__default.default.relative(cwd, filePath) : filePath,
1026
+ size,
1027
+ sourceFileName,
1028
+ exportPath
1029
+ });
996
1030
  });
997
- return null;
998
1031
  }
999
1032
  };
1000
1033
  },
@@ -1189,7 +1222,8 @@ async function bundle(entryPath, { cwd: _cwd, ...options } = {}) {
1189
1222
  entries
1190
1223
  });
1191
1224
  const pluginContext = {
1192
- sizeCollector
1225
+ sizeCollector,
1226
+ moduleDirectiveLayerMap: new Map()
1193
1227
  };
1194
1228
  const buildConfigs = await buildEntryConfig(entries, pkg, exportPaths, options, cwd, defaultTsOptions, pluginContext, false);
1195
1229
  const assetsJobs = buildConfigs.map((rollupConfig)=>bundleOrWatch(rollupConfig));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunchee",
3
- "version": "4.2.0",
3
+ "version": "4.2.2",
4
4
  "description": "zero config bundler for js/ts/jsx libraries",
5
5
  "bin": "./dist/bin/cli.js",
6
6
  "main": "./dist/index.js",
@@ -25,6 +25,8 @@
25
25
  "jsx",
26
26
  "zero-config",
27
27
  "library",
28
+ "css",
29
+ "web",
28
30
  "server components"
29
31
  ],
30
32
  "files": [
@@ -86,7 +88,8 @@
86
88
  "prettier": "^3.0.0",
87
89
  "react": "^18.2.0",
88
90
  "tsx": "^4.6.2",
89
- "typescript": "^5.3.2"
91
+ "typescript": "^5.3.2",
92
+ "bunchee": "link:./"
90
93
  },
91
94
  "lint-staged": {
92
95
  "*.{ts,tsx,js,jsx,md,json,yml}": "prettier --write"