{"id":21331115,"url":"https://github.com/trigensoftware/bdsl-webpack-plugin","last_synced_at":"2025-07-03T15:11:36.603Z","repository":{"id":42927952,"uuid":"241588495","full_name":"TrigenSoftware/bdsl-webpack-plugin","owner":"TrigenSoftware","description":"Browserslist Differential Script Loading webpack plugin.","archived":false,"fork":false,"pushed_at":"2022-12-12T02:18:26.000Z","size":1853,"stargazers_count":12,"open_issues_count":33,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-17T12:03:07.808Z","etag":null,"topics":["browserslist","browserslist-useragent-regexp","differential-script-loading","differential-stylesheet-loading","html-webpack-plugin","plugin","useragent","webpack"],"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/TrigenSoftware.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-19T10:02:51.000Z","updated_at":"2023-12-23T16:27:21.000Z","dependencies_parsed_at":"2023-01-27T11:01:46.462Z","dependency_job_id":null,"html_url":"https://github.com/TrigenSoftware/bdsl-webpack-plugin","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/TrigenSoftware/bdsl-webpack-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrigenSoftware%2Fbdsl-webpack-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrigenSoftware%2Fbdsl-webpack-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrigenSoftware%2Fbdsl-webpack-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrigenSoftware%2Fbdsl-webpack-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TrigenSoftware","download_url":"https://codeload.github.com/TrigenSoftware/bdsl-webpack-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrigenSoftware%2Fbdsl-webpack-plugin/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261749173,"owners_count":23203989,"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":["browserslist","browserslist-useragent-regexp","differential-script-loading","differential-stylesheet-loading","html-webpack-plugin","plugin","useragent","webpack"],"created_at":"2024-11-21T22:29:22.235Z","updated_at":"2025-06-24T20:06:13.602Z","avatar_url":"https://github.com/TrigenSoftware.png","language":"JavaScript","readme":"# bdsl-webpack-plugin\n\n[![NPM version][npm]][npm-url]\n[![Node version][node]][node-url]\n[![Dependencies status][deps]][deps-url]\n[![Build status][build]][build-url]\n[![Coverage status][coverage]][coverage-url]\n[![Dependabot badge][dependabot]][dependabot-url]\n\n[npm]: https://img.shields.io/npm/v/bdsl-webpack-plugin.svg\n[npm-url]: https://npmjs.com/package/bdsl-webpack-plugin\n\n[node]: https://img.shields.io/node/v/bdsl-webpack-plugin.svg\n[node-url]: https://nodejs.org\n\n[peer-deps]: https://david-dm.org/TrigenSoftware/bdsl-webpack-plugin/peer-status.svg\n[peer-deps-url]: https://david-dm.org/TrigenSoftware/bdsl-webpack-plugin?type=peer\n\n[deps]: https://david-dm.org/TrigenSoftware/bdsl-webpack-plugin.svg\n[deps-url]: https://david-dm.org/TrigenSoftware/bdsl-webpack-plugin\n\n[build]: http://img.shields.io/travis/com/TrigenSoftware/bdsl-webpack-plugin/master.svg\n[build-url]: https://travis-ci.com/TrigenSoftware/bdsl-webpack-plugin\n\n[coverage]: https://img.shields.io/coveralls/TrigenSoftware/bdsl-webpack-plugin.svg\n[coverage-url]: https://coveralls.io/r/TrigenSoftware/bdsl-webpack-plugin\n\n[dependabot]: https://api.dependabot.com/badges/status?host=github\u0026repo=TrigenSoftware/bdsl-webpack-plugin\n[dependabot-url]: https://dependabot.com/\n\nA webpack plugin that automates generation of the differential script loading with [browserslist](https://github.com/browserslist/browserslist) and [browserslist-useragent-regexp](https://github.com/browserslist/browserslist-useragent-regexp).\n\n1) 🦔 Declare environments in `.browserslistrc` config like this:\n\n```\ndefaults\n\n[modern]\nlast 2 versions and last 1 year and not safari 12.1\n\n[actual]\nlast 2 years and not last 2 versions\n```\n\n2) 📝 Create `webpack.config.js` for [multiple outputs](https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations):\n\n```js\nfunction createWebpackConfig(env) {\n    return {\n        name:    env,\n        /* ... */\n        module:  {\n            rules: [{\n                test:    /\\.js$/,\n                exclude: /node_modules/,\n                loader:  'babel-loader',\n                options: {\n                    cacheDirectory: true,\n                    presets:        [\n                        ['@babel/preset-env', {\n                            modules:     false,\n                            useBuiltIns: 'usage',\n                            corejs:      3\n                        }]\n                    ],\n                    plugins:        [/* ... */]\n                }\n            }]\n        },\n        plugins: [\n            new HtmlWebpackPlugin({\n                template: 'src/index.html',\n                inject:   'head'\n            })\n        ]\n    };\n}\n```\n\n3) 🦄 Add `bdsl-webpack-plugin`:\n\n```js\nconst {\n    BdslWebpackPlugin,\n    getBrowserslistQueries,\n    getBrowserslistEnvList\n} = require('bdsl-webpack-plugin');\n\nfunction createWebpackConfig(env) {\n    return {\n        name:    env,\n        /* ... */\n        module:  {\n            rules: [{\n                test:    /\\.js$/,\n                exclude: /node_modules/,\n                loader:  'babel-loader',\n                options: {\n                    cacheDirectory: true,\n                    presets:        [\n                        ['@babel/preset-env', {\n                            /* ... */\n                            targets: getBrowserslistQueries({ env })\n                        }]\n                    ],\n                    plugins:        [/* ... */]\n                }\n            }]\n        },\n        plugins: [\n            new HtmlWebpackPlugin(/* ... */),\n            new BdslWebpackPlugin({ env })\n        ]\n    };\n}\n\nmodule.exports = [\n    ...getBrowserslistEnvList(),\n    undefined // to use default .browserslistrc queries\n].map(createWebpackConfig);\n```\n\n4) 🎉 Done! Now `index.html` will contain differential script loading:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eExample\u003c/title\u003e\n        \u003cscript\u003efunction dsl(a,s,c,l,i){c=dsld.createElement('script');c.async=a[0];c.src=s;l=a.length;for(i=1;i\u003cl;i++)c.setAttribute(a[i][0],a[i][1]);dslf.appendChild(c)}var dsld=document,dslf=dsld.createDocumentFragment(),dslu=navigator.userAgent,dsla=[[]];if(/((CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ +]+(13[_\\.]0|13[_\\.]([1-9]|\\d{2,})|(1[4-9]|[2-9]\\d|\\d{3,})[_\\.]\\d+)(?:[_\\.]\\d+)?)|(SamsungBrowser\\/(9\\.2|9\\.([3-9]|\\d{2,})|([1-9]\\d|\\d{3,})\\.\\d+|10\\.1|10\\.([2-9]|\\d{2,})|(1[1-9]|[2-9]\\d|\\d{3,})\\.\\d+))|(Edge\\/(79|([8-9]\\d|\\d{3,}))(?:\\.\\d+)?)|(HeadlessChrome((?:\\/79\\.\\d+\\.\\d+)?|(?:\\/([8-9]\\d|\\d{3,})\\.\\d+\\.\\d+)?))|((Chromium|Chrome)\\/(79|([8-9]\\d|\\d{3,}))\\.\\d+(?:\\.\\d+)?)|(Version\\/(13|(1[4-9]|[2-9]\\d|\\d{3,}))\\.\\d+(?:\\.\\d+)?.*Safari\\/)|(Firefox\\/(68|(69|[7-9]\\d|\\d{3,})|71|(7[2-9]|[8-9]\\d|\\d{3,}))\\.\\d+\\.\\d+)|(Firefox\\/(68|(69|[7-9]\\d|\\d{3,})|71|(7[2-9]|[8-9]\\d|\\d{3,}))\\.\\d+(pre|[ab]\\d+[a-z]*)?)/.test(dslu))dsl(dsla[0],\"/index.modern.js\")\nelse if(/((CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS)[ +]+(11[_\\.]3|11[_\\.]([4-9]|\\d{2,})|(1[2-9]|[2-9]\\d|\\d{3,})[_\\.]\\d+|12[_\\.]0|12[_\\.]([1-9]|\\d{2,})|12[_\\.]4|12[_\\.]([5-9]|\\d{2,})|(1[3-9]|[2-9]\\d|\\d{3,})[_\\.]\\d+)(?:[_\\.]\\d+)?)|(SamsungBrowser\\/(7\\.2|7\\.([3-9]|\\d{2,})|7\\.4|7\\.([5-9]|\\d{2,})|([8-9]|\\d{2,})\\.\\d+|8\\.2|8\\.([3-9]|\\d{2,})|(9|\\d{2,})\\.\\d+))|(Edge\\/(17|(1[8-9]|[2-9]\\d|\\d{3,}))(?:\\.\\d+)?)|(HeadlessChrome((?:\\/65\\.\\d+\\.\\d+)?|(?:\\/(6[6-9]|[7-9]\\d|\\d{3,})\\.\\d+\\.\\d+)?))|((Chromium|Chrome)\\/(65|(6[6-9]|[7-9]\\d|\\d{3,}))\\.\\d+(?:\\.\\d+)?([\\d.]+$|.*Safari\\/(?![\\d.]+ Edge\\/[\\d.]+$)))|(Version\\/(11\\.1|11\\.([2-9]|\\d{2,})|(1[2-9]|[2-9]\\d|\\d{3,})\\.\\d+|12\\.0|12\\.([1-9]|\\d{2,})|(1[3-9]|[2-9]\\d|\\d{3,})\\.\\d+)(?:\\.\\d+)?.*Safari\\/)|(Firefox\\/(59|([6-9]\\d|\\d{3,}))\\.\\d+\\.\\d+)|(Firefox\\/(59|([6-9]\\d|\\d{3,}))\\.\\d+(pre|[ab]\\d+[a-z]*)?)/.test(dslu))dsl(dsla[0],\"/index.actual.js\")\nelse dsl(dsla[0],\"/index.legacy.js\");dsld.all[1].appendChild(dslf)\u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\u003c/body\u003e\n\u003c/html\u003e\n```\n\n[Here you can see complete `webpack.config.js` example.](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/basic/webpack.config.js)\n\n## Install\n\n```bash\nnpm i -D bdsl-webpack-plugin\n# or\nyarn add -D bdsl-webpack-plugin\n```\n\n## ⚠️ Before you start ⚠️\n\n1) `bdsl-webpack-plugin` captures scripts only from `\u003chead\u003e` section, so with `html-webpack-plugin` you should use `inject: 'head'` option;\n2) By default scripts are loaded [asynchronously](https://javascript.info/script-async-defer#dynamic-scripts) and executed in \"as they defined\" order. To execute script in \"load-first\" order you should add [`async`](https://javascript.info/script-async-defer#async) attribute to `\u003cscript\u003e` tag. For that you can use [`script-ext-html-webpack-plugin`](https://github.com/numical/script-ext-html-webpack-plugin);\n3) `defer` scripts are not supported, so you can use libraries like [`when-dom-ready`](https://www.npmjs.com/package/when-dom-ready) to bootstrap code when `DOM` ready;\n4) Webpack configs must be in modern to legacy browser order, e.g. `['modern', 'actual', 'legacy']`;\n5) `bdsl-webpack-plugin` also defines `process.env.BDSL_ENV` variable with bundle's environment.\n\n## Why?\n\nThere is a differential script loading with [module/nomodule trick](https://dev.to/thejohnstew/differential-serving-3dkf), for this you can use [`webpack-module-nomodule-plugin`](https://www.npmjs.com/package/webpack-module-nomodule-plugin). But browsers that support `type=module` already have new JS-features with different level of support. For example: [optional chaining operator](https://caniuse.com/#feat=mdn-javascript_operators_optional_chaining) (for comparison [browsers with `type=module` support](https://caniuse.com/#feat=es6-module)).\n\n## Plugin options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| isModule | `boolean` | — | Use `type=module` support check instead of RegExp. Should be used only on certain build. |\n| browsers | `string \\| string[]` | — | Manually provide a browserslist query (or an array of queries). It overrides the browserslist configuration specified in your project. |\n| env | `string` | — | When multiple browserslist [environments](https://github.com/ai/browserslist#environments) are specified, pick the config belonging to this environment. |\n| ignorePatch | `boolean` | `true` | Ignore the difference in patch browser numbers. |\n| ignoreMinor | `boolean` | `false` | Ignore the difference in minor browser versions. |\n| allowHigherVersions | `boolean` | `true` | For all browsers in the browserslist query, return a match if the useragent version is equal to or higher than the one specified in browserslist. |\n| allowZeroSubverions | `boolean` | `true` | Ignore match of patch or patch and minor, if they are 0. |\n| withStylesheets | `boolean` | `false` | Enable differential stylesheets loading. |\n| unsafeUseDocumentWrite | `boolean` | `false` | Use `document.write()` to inject `\u003cscript\u003e`. This variant supports `defer` scripts, [but some browsers can restrict `document.write()` calls](https://developers.google.com/web/updates/2016/08/removing-document-write). |\n\n## JS API\n\nRead docs [here](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/JS-API.md).\n\n## Examples\n\n- [Basic](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/basic/)\n- [`isModule` option with `@babel/preset-modules`](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/esm/)\n- [Differential stylesheet loading](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/postcss-preset-env/)\n- [Transpile dependencies](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/transpile-dependencies/)\n- [`unsafeUseDocumentWrite` option](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/document-write/)\n- [Differential serving with `SsrBdslWebpackPlugin`](https://github.com/TrigenSoftware/bdsl-webpack-plugin/blob/master/examples/SsrBdslWebpackPlugin/)\n- [`BdslBuilder` API with `@loadable/server`](https://github.com/TrigenSoftware/DevFest-Siberia/blob/5f69fd81361896a6ca77256cb04dbea1e6842b30/src/App/render.tsx#L159)\n\n## Metrics\n\nYou can get speed metrics from any site using devtool from this repo.\n\n1) Clone repo:\n\n```bash\ngit clone git@github.com:TrigenSoftware/bdsl-webpack-plugin.git\n```\n\n2) Install dependencies:\n\n```bash\nyarn\n```\n\n3) Now you can run script:\n\n```bash\nyarn measure \\\n\"https://nodsl.site.com/\" \\\n\"https://site.com/\"\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eOutput example\u003c/summary\u003e\n\n```bash\nhttps://nodsl.site.com/\n\nAverage time: 1s 303ms\nFastest time: 1s 203ms\nSlowest time: 2s 432ms\nEncoded size: 292 kB\nDecoded size: 1.08 MB\n\nhttps://site.com/\n\nAverage time: 1s 274ms\nFastest time: 1s 140ms\nSlowest time: 2s 284ms\nEncoded size: 218 kB\nDecoded size: 806 kB\n```\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n    \u003csummary\u003eParameters\u003c/summary\u003e\n\nEnvironment variables:\n\n```\nMEASURE_TIMES - number of site measurements, 10 by default\n```\n\nOptions:\n\n```\n--good3g - enable \"Good 3G\" network preset\n--regular4g - enable \"Regular 4G\" network preset\n--cache - enable resource caching\n```\n\u003c/details\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrigensoftware%2Fbdsl-webpack-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrigensoftware%2Fbdsl-webpack-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrigensoftware%2Fbdsl-webpack-plugin/lists"}