{"id":22160571,"url":"https://github.com/rozek/build-configuration-study","last_synced_at":"2025-10-23T17:29:00.697Z","repository":{"id":114382909,"uuid":"382776052","full_name":"rozek/build-configuration-study","owner":"rozek","description":"How difficult can it be to configure a modern JavaScript build chain? VERY","archived":false,"fork":false,"pushed_at":"2022-03-01T06:09:36.000Z","size":303,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-29T20:29:59.197Z","etag":null,"topics":["amd-modules","cjs","es-modules","esm","javascript","rollup","svelte3","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rozek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-04T06:02:42.000Z","updated_at":"2024-02-16T05:02:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"fd17ed5f-75c1-4736-8e28-48e6d01b5abb","html_url":"https://github.com/rozek/build-configuration-study","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Fbuild-configuration-study","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Fbuild-configuration-study/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Fbuild-configuration-study/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Fbuild-configuration-study/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rozek","download_url":"https://codeload.github.com/rozek/build-configuration-study/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245294778,"owners_count":20591919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amd-modules","cjs","es-modules","esm","javascript","rollup","svelte3","typescript"],"created_at":"2024-12-02T04:08:47.623Z","updated_at":"2025-10-23T17:28:55.679Z","avatar_url":"https://github.com/rozek.png","language":"JavaScript","readme":"# build-configuration-study #\n\nHow difficult can it be to configure a modern JavaScript build chain? VERY\n\n... but it *is* feasible!\n\n## Background Information ##\n\nNowadays, web applications often consist of many modules, which in turn can also be made up of modules themselves.\n\nAbove a certain number, the individual loading of each module by the browser takes too long - that's why developers usually bundle many small modules together into larger ones.\n\nSince often not all exported values and functions are needed from individual modules, a process called \"tree shaking\" is used to remove all unnecessary exports during bundling.\n\nUnfortunately, the requirements of a \"bundler\" for the modules to be used are different from those of a browser. In addition, some environments (such as, e.g., Node.js or Svelte) have further requirements that must also be met. And those who do not program in native JavaScript but require a preprocessor (as in the case of TypeScript, for example) face further difficulties.\n\nAnd to top it all off, a programmer has to painstakingly gather the individual requirements from the Internet - taking into account only the relevant ones and neglecting all outdated (or possibly even incorrect) publications.\n\nThe author has walked this rocky road for the following scenarios:\n\n* creating Svelte components (in general, or Svelte applications in particular)\n* creating JavaScript modules specifically for Svelte\n* creating general purpose JavaScript modules\n\nunder the following conditions\n\n* programming in TypeScript\n* bundling (and preprocessing et al.) using rollup\n* publishing as npm package\n\n### Relevance for Programmers with different Development Environments ###\n\n* **Developers not using Svelte**\n\t* may simply ignore the creation of Svelte components or modules which are specifically made for Svelte\n\t* but should definitely still consider the `svelte` field in `package.json` files to facilitate the use of their modules for Svelte users\n* **non-TypeScript Programmers**\u003cbr\u003ejust replace TypeScript with a preprocessor of their choice and adjust the rollup plugins accordingly\n* **users of other bundlers than Rollup**\u003cbr\u003emay still follow the requirements for `package.json` files and configure the bundler of their choice accordingly\n* **Developers not publishing npm packages**\u003cbr\u003emay still have to create the artifacts mentioned in `package.json` files even if they deploy them in other ways\n\n### Practical Examples ###\n\nThe patterns shown below have been backed (and verified) by practical (albeit artificially constructed) examples:\n\n* `throw-error` represents a simple module without any dependencies\n* `expected-ordinal` represents a module with own dependencies\n* `svelte-timer-action` represents a module (with dependencies) which has been specifically made for Svelte\n* `svelte-countdown-view` represents a Svelte component (with dependencies, Svelte applications are just special forms of Svelte components)\n\nFor each of these use cases, the files\n\n* `package.json` and\n* `rollup.config.js`\n\nare described and the tools used mentioned.\n\nIn the end, the different parts are each assembled into a web page that uses bundled or unbundled artifacts: just load the files `example-with-bundled-component.html` or `example-with-unbundled-component.html`, resp., into your browser.\n\n## throw-error ##\n\n`throw-error` represents a simple module without any dependencies. The module has been written in TypeScript and exports a single function `throwError` which simply throws a named JavaScript `Error` built from a given message.\n\nIt may be used\n\n* in a bundler as an (unbundled) ECMAScript module (ESM)\n* in Node.js as an (unbundled) CommonJS module (CJS)\n* in a browser as an (unbundled) AMD module or simply from a global variable\n* within Svelte (unbundled)\n\nSince `throw-error` does not have any dependencies, there is also no need for any bundling.\n\n### Tools used ###\n\nThe author often uses the following set of tools for building JavaScript modules written in TypeScript\n\n* `npm init` (you will have to answer some questions)\u003cbr\u003ebecause the modules are going to be published using npm\n* `npm install --save-dev rollup`\u003cbr\u003ethat's the bundler the author uses (standard bundler for svelte)\n* `npm install --save-dev typescript`\u003cbr\u003ebecause the author now only programs in TypeScript\n* `npm install --save-dev rimraf`\u003cbr\u003eto cleanup folders at the beginning of a new build\n* `npm install --save-dev @rollup/plugin-typescript`\u003cbr\u003eto let rollup handle TypeScript properly\n* `npm install --save-dev rollup-plugin-terser`\u003cbr\u003efor (optional) minification\n* `npm install --save-dev agadoo`\u003cbr\u003e`agadoo` helps validating that the built (unbundled) artifact can be \"tree-shaken\"\n\nSince this module does not have any dependencies, Rollup does not have to be told how to find and handle CommonJS modules\n\n### package.json ###\n\nThe full npm package description (`package.json`) can be found in the subfolder for this package within this repository. Shown here are the most important lines only (with some comments attached that should not find their way into the actual JSON file, though)\n\n```javascript\n  \"type\": \"module\", // tell Node.js to prefer ESM over CJS zu\n  \"main\":    \"./dist/throw-error.js\", // points to the UMD module, UNPKG needs it\n//\"browser\": \"./dist/throw-error.js\", // instead of \"main\" if pkg is for browsers only\n  \"module\": \"./dist/throw-error.esm.js\", // points to the ESM module\n  \"svelte\": \"./dist/throw-error.esm.js\", // points to what Svelte should use\n  \"types\":  \"./dist/throw-error.d.ts\",   // points to type declarations\n  \"exports\": {\n    \".\": {\n      \"require\":\"./dist/throw-error.js\",    // \"require\" the UMD file\n      \"import\": \"./dist/throw-error.esm.js\" // \"import\" the ESM file\n    },\n    \"./package.json\":\"./package.json\" // Svelte wants it so\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist \u0026\u0026 rollup -c rollup.config.js \u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist/ \u0026\u0026 rm src/*.js\",\n    \"agadoo\":\"agadoo\",\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\"\n  },\n```\n\nNote: the extra invocation of the TypeScript compiler (`tsc`) is required in order to properly generate a type declaration file (see [issue 105](https://github.com/rollup/plugins/issues/105) of the `@rollup/plugin-typescript` plugin - if you don't need such a file, you may safely remove the whole `\u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist \u0026\u0026 rm src/*.js` command chain from the \"scripts.build\" line.\n\n### rollup.config.js ###\n\nThe `rollup.config.js` shown below configures Rollup for two runs:\n\n* the first iteration creates an UMD module (which serves the need for CJS and AMD modules and a global variable pointing to the module's export\n* the second run creates the unbundled ECMAScript module\n\n```javascript\nimport typescript from '@rollup/plugin-typescript'\n//import { terser } from 'rollup-plugin-terser' // uncomment for minification\n\nexport default {\n  input: './src/throw-error.ts',\n  output: [\n    {\n      file:     './dist/throw-error.js',\n      format:    'umd',        // builds for both Node.js and Browser\n      name:      'throwError', // required for UMD modules\n      noConflict:true,\n      sourcemap: true,\n//    plugins: [terser({ format:{ comments:false, safari10:true } })], // dto.\n    },{\n      file:     './dist/throw-error.esm.js',\n      format:   'esm',\n      sourcemap:true,\n    }\n  ],\n  plugins: [\n    typescript(),\n  ],\n}\n```\n\nIf you want the UMD module to be minified, just uncomment the lines mentioning the `terser`.\n\n### tsconfig.json ###\n\n`tsconfig.json` is used to configure the TypeScript compiler. The full configuration can be found in the subfolder for this package within this repository. Shown here are the most important lines only - in contrast to `package.json`, this file *may* contain comments.\n\n```javascript\n  \"include\":[\"./src/**/*.ts\"],\n  \"exclude\":[],\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",   /* rollup wants it so */\n    \"declaration\": true,  /* for a '.d.ts' file */\n    \"outDir\":  \"./\",\n    \"rootDir\": \"./\",\n\n    \"moduleResolution\": \"node\", /* to work with NPM packages */\n    \"esModuleInterop\":  true,   /* for interoperability between CJS and ESM */\n  }\n```\n\n## expect-ordinal ##\n\n`expect-ordinal` represents a module with own dependencies. The module has been written in TypeScript and exports a single function `expectOrdinal` which checks if a given value is an ordinal JavaScript number and throws an error if not.\n\nIt may be used\n\n* in a bundler as an (unbundled) ECMAScript module (ESM)\n* in Node.js as a (partially) bundled or unbundled CommonJS module (CJS)\n* in a browser as a (partially) bundled or unbundled AMD module or simply from a global variable\n* within Svelte (unbundled)\n\nSince `expect-ordinal` does have its own dependencies (in contrast to `throw-error`), the need for (fully or partially) bundled artifact may arise.\n\n### Tools used ###\n\nSince `expect-ordinal` does have its own dependencies (in form of npm packages), Rollup has to be instructed how to find and handle them:\n\n* `npm init` (you will have to answer some questions)\u003cbr\u003ebecause the modules are going to be published using npm\n* `npm install --save-dev rollup`\u003cbr\u003ethat's the bundler the author uses (standard bundler for svelte)\n* `npm install --save-dev typescript`\u003cbr\u003ebecause the author now only programs in TypeScript\n* `npm install --save-dev rimraf`\u003cbr\u003eto cleanup folders at the beginning of a new build\n* `npm install --save-dev @rollup/plugin-node-resolve`\u003cbr\u003eto allow rollup looking for installed npm modules\n* `npm install --save-dev @rollup/plugin-commonjs`\u003cbr\u003ebecause npm modules are still often CJS modules (rather than ECMAScript modules)\n* `npm install --save-dev @rollup/plugin-typescript`\u003cbr\u003eto let rollup handle TypeScript properly\n* `npm install --save-dev rollup-plugin-terser`\u003cbr\u003efor (optional) minification\n* `npm install --save-dev agadoo`\u003cbr\u003e`agadoo` helps validating that the built (unbundled) artifact can be \"tree-shaken\"\n\n### package.json ###\n\nThe full npm package description (`package.json`) can be found in the subfolder for this package within this repository. Shown here are the most important lines only (with some comments attached that should not find their way into the actual JSON file, though)\n\n```javascript\n  \"type\": \"module\", // tell Node.js to prefer ESM over CJS\n  \"main\":    \"./dist/expect-ordinal.js\", // points to the UMD module, UNPKG needs it\n//\"browser\": \"./dist/expect-ordinal.bundled.js\", // instead of \"main\" if pkg is for browsers only\n  \"module\": \"./dist/expect-ordinal.esm.js\", // points to the ESM module\n  \"svelte\": \"./dist/expect-ordinal.esm.js\", // points to what Svelte should use\n  \"types\":  \"./dist/expect-ordinal.d.ts\",   // points to type declarations\n  \"exports\": {\n    \".\": {\n      \"require\":\"./dist/expect-ordinal.js\",    // \"require\" the UMD file\n      \"import\": \"./dist/expect-ordinal.esm.js\" // \"import\" the ESM file\n    },\n    \"./package.json\":\"./package.json\" // Svelte wants it so\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist \u0026\u0026 rollup -c rollup.config.js \u0026\u0026 rollup -c rollup-bundling.config.js \u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist/ \u0026\u0026 rm src/*.js\",\n    \"agadoo\":\"agadoo\",\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\"\n  },\n```\n\nThis variant of `package.json` reflects the fact that the module is built once with and once without bundling.\n\nNote: the extra invocation of the TypeScript compiler (`tsc`) is required in order to properly generate a type declaration file (see [issue 105](https://github.com/rollup/plugins/issues/105) of the `@rollup/plugin-typescript` plugin - if you don't need such a file, you may safely remove the whole `\u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist \u0026\u0026 rm src/*.js` command chain from the \"scripts.build\" line.\n\n### rollup.config.js ###\n\nIf no (or only partial) bundling is wanted, the `rollup.config.js` should list all packages that should *not* be bundled and specify a global variable name for each of them:\n\n```javascript\nimport commonjs   from '@rollup/plugin-commonjs'\nimport resolve    from '@rollup/plugin-node-resolve'\nimport typescript from '@rollup/plugin-typescript'\n//import { terser } from 'rollup-plugin-terser' // uncomment for minification\n\nexport default {\n  input: './src/expect-ordinal.ts',\n  external:['throw-error'],                  // list of (unbundled) dependencies\n  output: [\n    {\n      file:     './dist/expect-ordinal.js',\n      format:    'umd',           // builds for both Node.js and Browser\n      name:      'expectOrdinal', // required for UMD modules\n      globals:   { 'throw-error':'throwError' },  // globals for unbundled dep.s\n      noConflict:true,\n      sourcemap: true,\n//    plugins: [terser({ format:{ comments:false, safari10:true } })],\n    },{\n      file:     './dist/expect-ordinal.esm.js',\n      format:   'esm',\n      sourcemap:true,\n    }\n  ],\n  plugins: [\n    resolve(), commonjs(), typescript(),\n  ],\n}\n```\n\n### rollup-bundling.config.js ###\n\nIf bundling is wanted, the need for the field `external` and `option.globals` no longer exists:\n\n```javascript\nimport commonjs   from '@rollup/plugin-commonjs'\nimport resolve    from '@rollup/plugin-node-resolve'\nimport typescript from '@rollup/plugin-typescript'\n//import { terser } from 'rollup-plugin-terser' // uncomment for minification\n\nexport default {\n  input: './src/expect-ordinal.ts',\n  output:{\n    file:     './dist/expect-ordinal.bundled.js',\n    format:    'umd',           // builds for both Node.js and Browser\n    name:      'expectOrdinal', // required for UMD modules\n    noConflict:true,\n    sourcemap: true,\n//  plugins: [terser({ format:{ comments:false, safari10:true } })],\n  },\n  plugins: [\n    resolve(), commonjs(), typescript(),\n  ],\n}\n```\n\n### tsconfig.json ###\n\n`tsconfig.json` is used to configure the TypeScript compiler. The full configuration can be found in the subfolder for this package within this repository. Shown here are the most important lines only - in contrast to `package.json`, this file *may* contain comments.\n\n```javascript\n  \"include\":[\"./src/**/*.ts\"],\n  \"exclude\":[],\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",   /* rollup wants it so */\n    \"declaration\": true,  /* for a '.d.ts' file */\n    \"outDir\":  \"./\",\n    \"rootDir\": \"./\",\n\n    \"moduleResolution\": \"node\", /* to work with NPM packages */\n    \"esModuleInterop\":  true,   /* for interoperability between CJS and ESM */\n  }\n```\n\n## svelte-timer-action ##\n\n`svelte-timer-action` represents a module (with dependencies) which has been specifically made for Svelte. The module has been written in TypeScript and exports a single function `Timer` which can be used as a Svelte action invoking a given callback once a second.\n\nSince `svelte-timer-action` may only be used within Svelte, there is never any need for bundling (as Svelte should always have access to the component's source code anyway). This restriction also simplifies configuration of the build chain.\n\n### Tools used ###\n\nSince Svelte should always get access to the source code of a module (perhaps after any preprocessing - e.g., transpilation), there is no need for bundling and minification:\n\n* `npm init` (you will have to answer some questions)\u003cbr\u003ebecause the modules are going to be published using npm\n* `npm install --save-dev rollup`\u003cbr\u003ethat's the bundler the author uses (standard bundler for svelte)\n* `npm install --save-dev typescript`\u003cbr\u003ebecause the author now only programs in TypeScript\n* `npm install --save-dev rimraf`\u003cbr\u003eto cleanup folders at the beginning of a new build\n* `npm install --save-dev @rollup/plugin-node-resolve`\u003cbr\u003eto allow rollup looking for installed npm modules\n* `npm install --save-dev @rollup/plugin-commonjs`\u003cbr\u003ebecause npm modules are still often CJS modules (rather than ECMAScript modules)\n* `npm install --save-dev @rollup/plugin-typescript`\u003cbr\u003eto let rollup handle TypeScript properly\n* `npm install --save-dev agadoo`\u003cbr\u003e`agadoo` helps validating that the built (unbundled) artifact can be \"tree-shaken\"\n\nSimilar to `throw-error` you may omit `@rollup/plugin-node-resolve` and `@rollup/plugin-commonjs` if your action does not have any dependencies.\n\n### package.json ###\n\nThe full npm package description (`package.json`) can be found in the subfolder for this package within this repository. Shown here are the most important lines only (with some comments attached that should not find their way into the actual JSON file, though)\n\n```javascript\n  \"module\": \"./dist/svelte-timer-action.esm.js\",\n  \"svelte\": \"./dist/svelte-timer-action.esm.js\", // points to what Svelte should use\n  \"types\":  \"./dist/svelte-timer-action.d.ts\",   // points to type declarations\n  \"exports\": {\n    \"./package.json\":\"./package.json\" // Svelte wants it so\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist \u0026\u0026 rollup -c rollup.config.js \u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist/ \u0026\u0026 rm src/*.js*\",\n    \"agadoo\":\"agadoo ./dist/svelte-timer-action.esm.js\",\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\"\n  },\n```\n\nNote I: the extra invocation of the TypeScript compiler (`tsc`) is required in order to properly generate a type declaration file (see [issue 105](https://github.com/rollup/plugins/issues/105) of the `@rollup/plugin-typescript` plugin - if you don't need such a file, you may safely remove the whole `\u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist \u0026\u0026 rm src/*.js` command chain from the \"scripts.build\" line.\n\nNote II: the \"agadoo\" script had to be changed since there is no longer a `main` field in this package description.\n\nNote III: you may still decide to treat Svelte actions like any other JavaScript module and, e.g., build an UMD module which can be loaded separately into a browser (but do not forget to add a `main` or `browse` field to your `package.json` then: [UNPKG](https://unpkg.com/) needs it) - it's just that this situation rarely occurs.\n\n### rollup.config.js ###\n\nAgain, in order to avoid bundling, a list of all external dependencies should be provided - however, the need for specifying global variable names does not apply:\n\n```javascript\nimport commonjs   from '@rollup/plugin-commonjs'\nimport resolve    from '@rollup/plugin-node-resolve'\nimport typescript from '@rollup/plugin-typescript'\n\nexport default {\n  input: './src/svelte-timer-action.ts',\n  external:['throw-error'],                  // list of (unbundled) dependencies\n  output: {\n    file:     './dist/svelte-timer-action.esm.js',\n    format:   'esm',\n    sourcemap:true,\n  },\n  plugins: [\n    resolve({ browser:true, dedupe:['svelte'] }), commonjs(), typescript(),\n  ],\n}\n```\n\nSimilar to `throw-error` you may omit any `commonjs` and `resolve` imports and invocations if your action does not have any dependencies.\n\n### tsconfig.json ###\n\n`tsconfig.json` is used to configure the TypeScript compiler. The full configuration can be found in the subfolder for this package within this repository. Shown here are the most important lines only - in contrast to `package.json`, this file *may* contain comments.\n\n```javascript\n  \"include\":[\"./src/**/*.ts\"],\n  \"exclude\":[],\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",   /* rollup wants it so */\n    \"declaration\": true,  /* for a '.d.ts' file */\n    \"outDir\":  \"./\",\n    \"rootDir\": \"./\",\n\n    \"moduleResolution\": \"node\", /* to work with NPM packages */\n    \"esModuleInterop\":  true,   /* for interoperability between CJS and ESM */\n  }\n```\n\n## svelte-countdown-view ##\n\n`svelte-countdown-view` represents a Svelte component (with dependencies). The component has been written in TypeScript and exports a simple countdown timer.\n\nIt may be used\n\n* in a bundler as an (unbundled) ECMAScript module (ESM)\n* in Node.js as a (partially) bundled or unbundled CommonJS module (CJS)\n* in a browser as a (partially) bundled or unbundled AMD module or simply from a global variable\n* within Svelte (unbundled)\n\nIn contrast to `expected-ordinal`, the build chain for this module now also has to include the Svelte compiler.\n\n### Tools used ###\n\nNow that the Svelte compiler has to be used, the list of tools becomes a little bit longer:\n\n* `npm init` (you will have to answer some questions)\u003cbr\u003ebecause the modules are going to be published using npm\n* `npm install --save-dev rollup`\u003cbr\u003ethat's the bundler the author uses (standard bundler for svelte)\n* `npm install --save-dev typescript`\u003cbr\u003ebecause the author now only programs in TypeScript\n* `npm install --save-dev rimraf`\u003cbr\u003eto cleanup folders at the beginning of a new build\n* `npm install --save-dev @rollup/plugin-node-resolve`\u003cbr\u003eto allow rollup looking for installed npm modules\n* `npm install --save-dev @rollup/plugin-commonjs`\u003cbr\u003ebecause npm modules are still often CJS modules (rather than ECMAScript modules)\n* `npm install --save-dev @rollup/plugin-typescript`\u003cbr\u003eto let rollup handle TypeScript properly\n* `npm install --save-dev svelte rollup-plugin-svelte`\u003cbr\u003eto let rollup handle Svelte components properly\n* `npm install --save-dev svelte-preprocess`\u003cbr\u003ebecause Svelte files contain HTML, CSS and JavaScript all together\n* `npm install --save-dev @tsconfig/svelte`\u003cbr\u003eTypeScript compiler configuration defaults for Svelte\n* `npm install --save-dev rollup-plugin-postcss`\u003cbr\u003ebecause Svelte files also contain CSS\n* `npm install --save-dev save-to-file`\u003cbr\u003ewrites the results of the Svelte preprocessing step into a file (see [save-to-file](https://github.com/rozek/save-to-file))\n* `npm install --save-dev rollup-plugin-terser`\u003cbr\u003efor (optional) minification\n\n### package.json ###\n\nThe full npm package description (`package.json`) can be found in the subfolder for this package within this repository. Shown here are the most important lines only (with some comments attached that should not find their way into the actual JSON file, though)\n\n```javascript\n  \"type\": \"module\", // tell Node.js to prefer ESM over CJS\n  \"browser\": \"./dist/svelte-countdown-view.bundled.js\", // because pkg is for browsers only\n  \"module\": \"./dist/svelte-countdown-view.esm.js\", // points to the ESM module\n  \"svelte\": \"./dist/svelte-countdown-view.svelte\", // points to what Svelte should use\n  \"types\":  \"./dist/svelte-countdown-view.d.ts\",   // points to type declarations\n  \"exports\": {\n    \".\": {\n      \"require\":\"./dist/svelte-countdown-view.js\",    // \"require\" the UMD file\n      \"import\": \"./dist/svelte-countdown-view.esm.js\" // \"import\" the ESM file\n    },\n    \"./package.json\":\"./package.json\" // Svelte wants it so\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist \u0026\u0026 rollup -c rollup.config.js \u0026\u0026 rollup -c rollup-bundling.config.js \u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist/ \u0026\u0026 rm src/*.js\",\n    \"agadoo\":\"agadoo\",\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\"\n  },\n```\n\nNote: the extra invocation of the TypeScript compiler (`tsc`) is required in order to properly generate a type declaration file (see [issue 105](https://github.com/rollup/plugins/issues/105) of the `@rollup/plugin-typescript` plugin - if you don't need such a file, you may safely remove the whole `\u0026\u0026 tsc \u0026\u0026 mv src/*.d.ts dist \u0026\u0026 rm src/*.js` command chain from the \"scripts.build\" line.\n\n### rollup.config.js ###\n\nAgain, it could be useful to create (partially) bundled and unbundled artifacts - here is the configuration for unbundled (or only partially bundled) ones (listing all modules that should not be bundled together with their global variable names):\n\n```javascript\nimport svelte         from 'rollup-plugin-svelte'\nimport commonjs       from '@rollup/plugin-commonjs'\nimport resolve        from '@rollup/plugin-node-resolve'\nimport autoPreprocess from 'svelte-preprocess'\nimport typescript     from '@rollup/plugin-typescript'\nimport postcss        from 'rollup-plugin-postcss'\nimport saveToFile     from 'save-to-file'\n//import { terser } from 'rollup-plugin-terser' // uncomment for minification\n\nexport default {\n  input: './src/index.ts',\n  external:[                                 // list of (unbundled) dependencies\n    'throw-error','expect-ordinal', // 'svelte-timer-action' // partial bundling\n  ],\n  output: [\n    {\n      file:     './dist/svelte-countdown-view.js',\n      format:    'umd',           // builds for both Node.js and Browser\n      name:      'CountdownView', // required for UMD modules\n      globals:   {                         // globals for unbundled dependencies\n        'throw-error':'throwError',\n        'expect-ordinal':'expectOrdinal',\n//      'svelte-timer-action':'Timer'                        // partial bundling\n      },\n      noConflict:true,\n      sourcemap: true,\n//    plugins: [terser({ format:{ comments:false, safari10:true } })],\n    },{\n      file:     './dist/svelte-countdown-view.esm.js',\n      format:   'esm',\n      sourcemap:true,\n    }\n  ],\n  plugins: [\n    svelte({ preprocess:[\n      autoPreprocess({ aliases:[['ts','typescript']] }),\n      saveToFile('./dist/svelte-countdown-view.svelte')\n    ]}),\n    resolve({ browser:true, dedupe:['svelte'] }), commonjs(), typescript(),\n    postcss({ extract:false, inject:{insertAt:'top'} }),\n  ],\n}\n```\n\nNote: this example demonstrates \"partial bundling\": assuming, that the `svelte-timer-action` will only be used by instances of `svelte-countdown-view`, whereas `throw-error` and `expect-ordinal` could be of general use (and, thus, run the risk of being loaded multiple times), `svelte-timer-action` is directly bundled into `svelte-countdown-view` in order to simplify its use on web pages (i.e., outside Svelte) - if you plan to write Svelte applications only, you may safely ignore this note (but then, you will not have to generate UMD modules anyway)\n\n### rollup-bundling.config.js ###\n\nThe Rollup configuration for bundled artefacts is simple - as usual:\n\n```javascript\nimport svelte         from 'rollup-plugin-svelte'\nimport commonjs       from '@rollup/plugin-commonjs'\nimport resolve        from '@rollup/plugin-node-resolve'\nimport autoPreprocess from 'svelte-preprocess'\nimport typescript     from '@rollup/plugin-typescript'\nimport postcss        from 'rollup-plugin-postcss'\n//import { terser } from 'rollup-plugin-terser' // uncomment for minification\n\nexport default {\n  input: './src/index.ts',\n  output:{\n    file:     './dist/svelte-countdown-view.bundled.js',\n    format:    'umd',           // builds for both Node.js and Browser\n    name:      'CountdownView', // required for UMD modules\n    noConflict:true,\n    sourcemap: true,\n//  plugins: [terser({ format:{ comments:false, safari10:true } })],\n  },\n  plugins: [\n    svelte({ preprocess:[\n      autoPreprocess({ aliases:[['ts','typescript']] })\n    ]}),\n    resolve({ browser:true, dedupe:['svelte'] }), commonjs(), typescript(),\n    postcss({ extract:false, inject:{insertAt:'top'} }),\n  ],\n}\n```\n\n### tsconfig.json ###\n\n`tsconfig.json` is used to configure the TypeScript compiler. The full configuration can be found in the subfolder for this package within this repository. Shown here are the most important lines only - in contrast to `package.json`, this file *may* contain comments.\n\nThe Svelte compiler requires some modifications compared to the configuration used for the other modules.\n\n```javascript\n  \"extends\": \"@tsconfig/svelte/tsconfig.json\",\n\n  \"include\": [\"src/**/*.ts\"],\n  \"exclude\": [\"node_modules/*\", \"__sapper__/*\", \"public/*\"],\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",   /* rollup wants it so */\n    \"declaration\": true,  /* for a '.d.ts' file */\n    \"outDir\":  \"./\",\n    \"rootDir\": \"./\",\n\n    \"moduleResolution\": \"node\", /* to work with NPM packages */\n    \"esModuleInterop\":  true,   /* for interoperability between CJS and ESM */\n  }\n```\n\n## License ##\n\n[MIT License](LICENSE.md)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frozek%2Fbuild-configuration-study","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frozek%2Fbuild-configuration-study","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frozek%2Fbuild-configuration-study/lists"}