{"id":14990655,"url":"https://github.com/noviel/webpack-features","last_synced_at":"2026-01-05T00:08:33.798Z","repository":{"id":98890884,"uuid":"96900788","full_name":"Noviel/webpack-features","owner":"Noviel","description":"Configure webpack quickly and without pain","archived":false,"fork":false,"pushed_at":"2018-07-03T12:25:50.000Z","size":786,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-26T08:22:07.717Z","etag":null,"topics":["bundle","css-modules","postcss","presets","react","typescript","webpack","webpack-features"],"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/Noviel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2017-07-11T14:11:40.000Z","updated_at":"2018-07-03T12:25:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"1e6abef5-66a3-4971-bf02-f4a11a9d997e","html_url":"https://github.com/Noviel/webpack-features","commit_stats":{"total_commits":207,"total_committers":2,"mean_commits":103.5,"dds":"0.024154589371980673","last_synced_commit":"fe90a4bb9d29b84bb9f6ccbc5a8dfd67c04b4ce5"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Noviel%2Fwebpack-features","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Noviel%2Fwebpack-features/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Noviel%2Fwebpack-features/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Noviel%2Fwebpack-features/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Noviel","download_url":"https://codeload.github.com/Noviel/webpack-features/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244888664,"owners_count":20526853,"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":["bundle","css-modules","postcss","presets","react","typescript","webpack","webpack-features"],"created_at":"2024-09-24T14:20:32.902Z","updated_at":"2026-01-05T00:08:33.737Z","avatar_url":"https://github.com/Noviel.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Webpack Features\n\nMake Webpack configuration process quick and painless.\n\n## Content\n\n- [Installation](#installation)\n  - Presets\n    - [Base](#base)\n    - [React](#react)\n    - [Examples](#examples)\n  - [Features](#features)\n    - [Initializing](#initializing)\n    - [createConfig](#createconfig)\n    - [entry](#entry)\n    - [output](#output)\n    - [javascript](#javascript)\n      - [TypeScript](#typescript)\n      - Plugins  \n        - [emotion](#emotion)\n    - [webAssembly](#webassembly)\n    - [styles](#styles)\n    - [images](#images)\n    - [namedModules](#namedmodules)\n    - [node](#node)\n    - [browser](#browser)\n    - [define](#define)\n    - [externals](#externals)\n    - [optimization](#optimization)\n\n## Installation\n\n```sh\nyarn add webpack-features --dev\n```\n\nor\n\n```sh\nnpm install webpack-features --save-dev\n```\n\n## Presets\n\nPresets provide complete configuration that can be used directly by Webpack.\n\n### Base\n\nPreset suitable for most applications with following features: ESNext syntax, CSS and media files loading, production/development environment, browsers/node.js targets and other (see options). Preset makes following assumption about structure of the project:\n\n- `src/index.js` - entry point of an application\n- `src/index.html` - html-template\n- `static` - output directory, `index.html` will be placed here \n- `static/dist` - bundled assets directory\n\nNotes:\n\n- for `node` target default output directory is `server`\n- CSS modules is enabled for `*.module.css` files (based on `styles` feature design decisions)\n\nDespite the fact that preset does not need any options, there are many parameters to customize behavior.\n\nBasic usage: \n\n```javascript\n// webpack.config.js\nconst { base } = require('webpack-features');\n\nmodule.exports = base({\n  entry: { index: './src/main.js' },\n  publicPath: './public/',\n});\n```\n\nComplete list of options with default values:\n\n```javascript\nbase(\n  {\n    // for multiple entries use object\n    // entry = {\n    //  index: './src/index.js',\n    //  other: './src/other.js',\n    // }\n    entry = './src/index.js',\n\n    // array with strings of frameworks\n    // 'react' - for React support\n    // other frameworks are coming soon..\n    frameworks = [],\n\n    production = process.env.NODE_ENV === 'production',\n\n    // selects the target, one of `node` or `browser` should be truthy\n    // \n    // node: if 'true' target will be set to 'current` node \n    node = false,\n    // browser: allowed values: 'legacy', 'modern' or [string]\n    // [string] - is a browserlist format, see https://github.com/browserslist/browserslist\n    browser = !node,\n\n    // enables hot reloading\n    hot = false,\n\n    // list of the defines for `define` feature\n    defines = {},\n\n    // will be used in html-webpack-plugin as a template\n    // set to falsy value to not use html-webpack-plugin\n    template = './src/index.html',\n\n    // absolute path of the project root directory\n    rootPath = fs.realpathSync(process.cwd()),\n\n    // webpack's publich path\n    publicPath = !production || node || hot ? '/' : '/dist/',\n\n    // relative path for a built assets output\n    distPath = browser ? 'static/dist/' : 'server',\n\n    // which type syntax should be used\n    // can be:\n    //  - flow\n    //  - typescript\n    types = 'none',\n\n    // CSS preprocessors\n    // should be an array of strings\n    // empty array - vanilla CSS\n    // can contain 'scss' and 'less'\n    cssPreprocessors = [],\n\n    // patterns to exclude from style loaders\n    cssExclude = false,\n\n    // use external babel configuration\n    babelrc = false,\n\n    // patterns to exclude from babel transformations\n    babelExclude = /node_modules/,\n\n    // add polyfills for features unsupported by environment\n    // 'inject' - add an entire babel polyfill to every entry,\n    //            so you don't need to import it from the code\n    // 'usage' - use @babel/preset-env to find only needed polyfills\n    //           and automatically import them\n    // true|'entry' - use @babel/preset-env, but you need to \n    //                write `import \"@babel/polyfill\"` in the code\n    // false - don't use polyfills\n    babelPolyfill = 'usage',\n\n    // support for WebWorkers\n    webWorkers = true,\n\n    // should build library instead of application\n    // string will be used as a library name,\n    library = false,\n\n    // list of external imports that should not be bundled\n    // for example: `node_modules` for node target will be added to externals automatically\n    externals = [],\n\n    // for build for node target\n    // array of strings or regular expressions which will be bundled\n    // usefull if you are using workspaces and include one package from another\n    externalsWhitelist = undefined,\n\n    // path to `node_modules` to exclude them if needed\n    modulesDir = 'node_modules',\n\n    // output html filename\n    // by default we want it to be at the root of the public folder\n    // and because of default `distPath` the root is one level higher\n    // but for `hot` reloading we should point to the virtual `index.html`\n    indexHtml: `${hot || !production ? '' : '../'}index.html`,\n\n    // false - do not support WebAssembly\n    // 'builtin' - use builtin Webpack WebAssembly loader\n    // `inline` - use specific loader, do not output *.wasm files, \n    //            embed code in JavaScript\n    wasm = 'builtin',\n\n    // add debug information output on bundling stage\n    debug = false\n  },\n  featuresOptionsOverrides = {},\n  webpackConfigOverrides = {},\n);\n```\n\nSecond and third parameters are objects with optional config extensions.\n\n`featuresOptionsOverrides` can be used in case preset is not providing needed options for features. Every option is an object named exactly like corresponding feature. These options will be flat merged with overrides to the features options generated by the preset.\n\n```javascript\nbase(\n  {/* features options */},\n  {\n    // this will remove eslint-loader from resulting config\n    javascript: {\n      eslint: false\n    }\n  }\n);\n```\n\n`webpackConfigOverrides` is a last resort! It can be used to add something to the config not provided by features. Should look like entries of the standard webpack config. Will be flat merged and therefore entries will completely override top-level options (e.g. entry, output, module) generated by features.\n\n```javascript\nbase(\n  {/* features options */},\n  {/* featuresOptionsOverrides must be here even is empty */},\n  {\n    // this will completely override `output` field!\n    output: {\n      chunkFilename: '[name].chunk.js',\n      filename: '[name].js',\n      path: 'my-crazy-path',\n      publicPath: '/',\n    },\n  }\n);\n```\n\n### React\n\nPreset with React support. It accepts same options as `base` preset. Usage:\n\n```javascript\n// webpack.config.js\nconst { react } = require('webpack-features');\n\nmodule.exports = react({\n  entry: { index: './src/main.js' },\n  publicPath: './public/',\n});\n```\n\n### Examples\n\n- [webpack-features/examples](https://github.com/Noviel/webpack-features/tree/master/examples)\n- [modern-frontend-starter](https://github.com/Noviel/modern-frontend-starter)\n\n## Features\n\nIf the above presets do not provide the necessary functionality or you want to create your own preset, you can use `features` that are the building blocks and the core of `webpack-features`.\n\n### Initializing\n\nPackage's default export is an initializing function that returns object with features.\n\n`createFeatures(env)`\n\nParameters:\n\n- **env**: `object`, required\n  - **target**: `object`, required\n    - **name**: `'browser'|'node'`\n    - **value**: `'modern'|'legacy'|'string'|undefined`\n  - **production**: `boolean`, required\n  - **rootPath**: `string`, absolute path to the project's root, **default**: `process.cwd()`\n  - **publicPath**: `string`, **default**: `'/'`\n  - **distPath**: `string`, relative path for output assets, **default**: `'dist'`\n  - **debug**: `boolean`, output debug information on bundling stage, **default**: `false`\n\n`env` defines an environment for which the config should be created. if `env.target.value` is undefined, will be used browserlist sources for `browser` target.\n\n```javascript\n// webpack.config.js\nconst createFeatures = require('webpack-features');\n\nconst env = {\n  target: { browsers: 'modern' },\n  production: process.env.NODE_ENV === 'production',\n  publicPath: '/',\n};\n\nconst features = createFeatures(env);\n```\n\nThen you can destructure result of initializing to get features.\n\n```javascript\nconst { createConfig, entry, javascript, styles } = createFeatures(env);\n```\n\n### createConfig\n\nMain function that creates complete final webpack config from features. Can accept native Webpack's config object's parts.\n\n`createConfig(...args)`\n\nParameters:\n\n- **args**: list of features and/or objects to be merged\n\n```javascript\nconst { createConfig, entry, javascript, styles } = createFeatures(env);\n\nmodule.exports = createConfig(\n  // feature\n  entry({ index: './src/index.js' }),\n  javascript(),\n  styles(),\n  // object with the standard webpack config part\n  {\n    output: {\n      path: DIST_PATH,\n      filename: '[name].js',\n    },\n  }\n);\n```\n\n### entry\n\nInclude entries to the config.\n\n`entry(options)`\n\nParameters:\n\n- **options**: `object`\n  - **entries**: `object` where keys are entries names and values are strings or arrays of strings with paths. required\n  - **options**: `object`\n    - **polyfill**: `boolean` - should include `babel-polyfill` into every entry. **default**: `true` for 'legacy' browsers target, otherwise `false`\n    - **hotMiddleware**: `boolean` - should include express middleware for hot reloading. **default**: `false`\n\n```javascript\nentry({ \n  entries: { index: './src/index.js' },\n  polyfill: true,\n  hotMiddleware: true,\n}),\n```\n\n### output\n\nDefine where to output the resulting bundle.\n\n`output(options)`\n\nParameters:\n\n- **options**: `object`\n  - **filename**: `string` name of the output file. **default**: for production `'[name].[chunkhash:8].js'`, otherwise `'[name].js'`.\n  - **chunkFilename**: `string`, name of chunks. **default**: for production `'[name].[chunkhash:8].js'`, otherwise `'[name].js'`.\n  - **library**: `string | boolean`. Used for building libraries, not applications. **default**: `false`. \n  - **libraryTarget**: `string`, type of the library module system. Used if `library` is not false. **default**: `'umd'`\n\n```javascript\noutput({ \n  filename: '[name]-[chunkhash].js',\n}),\n```\n\n### javascript\n\nIncludes in the config support of a modern javascript syntax. It uses `babel` and `babel-preset-env`. Preset's config depends on the provided `env.target`\n\nParameters:\n\n- **options**: `object`\n  - **babelrc**: `boolean`, use external babel configuration. **default**: `false`.\n  - **babelPlugins**: `array of strings`, additional `babel` plugins.\n  - **polyfill**: `'usage'|'entry'|false`, apply `@babel/preset-env` for `@babel/polyfill`. **default**: `'entry'` for legacy browsers.\n  - **syntaxEnhance**: `boolean`, should include non-standard language features. Includes `object rest spread`, `decorators`, `class properties`, `dynamic import`. **default**: `true`\n  - **eslint**: `boolean`, should include `eslint` for linting before transpiling. **default**: `true`\n  - **react**: `boolean`, should include `react` syntax support. **default**: true\n  - **flow**: `boolean`, should include `flow` support. **default**: true\n  - **typescript**: `'strict'|'migration'|false`, add support for `TypeScript`. `true` value is treated as `'strict'` **default**: `false`\n  - **tsOptions**: `object`, `ts-loader` options. **default**: `{}`\n  - **modules**: transform modules to specific format. `false` - do not transpile. **default**: `false` for browsers, `commonjs` for node\n  - **hot**: `boolean`, should include support for hot reloading. **defaul**: true for non-production browsers target\n  - **exclude**: items to exclude from loading. **default**: `/node_modules/`\n  - **workers**: `boolean`, add support for WebWorkers. **default**: `true`\n\n```javascript\njavascript({\n  // for example: we do not want to include every extended syntax plugin, but want specific one\n  babelPlugins: ['transform-object-rest-spread'],\n  syntaxEnhance: false,\n})\n```\n\n##### TypeScript\n\nYou should `yarn add typescript --dev` in order to use TypeScript. There are two default modes for TypeScript: `migration` and `strict`. One of built-in `tsconfig.json` files will be used depending on mode by default. Or you can use your own `tsconfig.json` pointing to this file in `javascript` feature options:\n\n```javascript\njavascript({\n  typescript: true,\n  tsOptions: {\n    configFile: require.resolve(`../tsconfig.json`),\n  },\n})\n```\n\n##### Plugins\n###### emotion\n\nAdds `babel-plugin-emotion` to the config.\n\n```javascript\nconst { emotion } = require('webpack-features');\n/* ... */\njavacript(config, [emotion(options)])\n```\n\nParameters:\n\n- **options**: `object`\n  - **hoist**: `boolean`, **default**: `production`\n  - **sourceMap**: `boolean`, **default**: `!production`\n  - **autoLabel**: `boolean`, **default**: `!production`\n\n### webAssembly\n\nAdd support for WebAssembly.\n\n`webAssembly(options)`\n\nParameters:\n\n- **options**: `object`\n  - **inline**: `boolean` - embed WebAssembly code into JavaScript. Multiple entries of the same code will be embedded for every entry. **default**: `false`\n  - **builtin**: `boolean` - enable Webpack 4 WebAssembly builtin loader. **default**: `true`\n\n```javascript\nwebAssembly({ inline: true, builtin: false )\n```\n\n### styles\n\nAdds support for styles.\n\n`styles(options)`\n\nParameters:\n\n- **options**: object\n  - **preprocessors** - `array of strings`, can include `'scss'`, `'less'`. **default**: []\n  - **cssModules** - one of: `'both'` - use global CSS and CSS Modules, `'only'` - only CSS Modules, `'exclude'` - only global CSS. **default**: 'both'\n  - **extract** - `boolean`, should extract styles to external file. **default**: true if `production` and browsers target\n  - **extractPlugin** - `boolean`, should add extract plugin to plugins list. **default**: same as **extract**\n  - **extractFilename** - `string`, name of the file for extraction. **default**: `'[name].css'`\n  - **postcss** - `false` means do not use postcss. Otherwise it should be a `callback` that returns a postcss config. It will be called as `postcss({ target, production })`, so you can conditionally include/exclude postcss parts. **default**: config with `precss` and `autoprefixer` based on browsers target.\n  - **exclude** - items to exclude from processing. **default**: `[/node_modules/]`\n\nSupports Sass/less preprocessors, but you should manually add corresponding packages if you want to use them.\n\nSass:\n\n```sh\nyarn add node-sass sass-loader --dev\n```\n\nless:\n```sh\nyarn add less less-loader --dev\n```\n\n**Important note**: CSS Modules (if enabled) will be applied to files with extension `.module.{css|less|scss}` only.\n\n```javascript\nstyles({\n  preprocessors: ['scss'],\n  cssModules: 'only',\n  extract: false,\n\n  postcss({ target, production }) {\n    return {\n      plugins: []\n        .concat(production ? autoprefixer: [])\n    };\n  },\n\n  exclude: false,\n})\n```\n\n### media\n\nLoads media files.\n\n`media(options)`\n\nParameters:\n\n- **limit**: `integer`, if the file is smaller then a limit, it will be encoded as a DataURL. **default**: 10000\n- **name**: `string`, modifies name of the file. **default**: for `production` `'[name].[ext]'`, otherwise `'media/[hash:8].[ext]'`\n\nSee [url-loader](https://github.com/webpack-contrib/url-loader) for more info.\n\n```javascript\nmedia({ limit: 4096, name: 'assets/media/[hash:8].[ext]' })\n```\n\n### namedModules\n\nAdd readable consistent names for chunks and modules.\n\n```javascript\nnamedModules(options)\n```\n\nParameters:\n\n- **options**: `object`\n  - **chunkName**: `function(chunk)`, chunk naming function.\n\n### node\n\nSet Webpack's target to `node`.\n\n```javascript\nnode()\n```\n\n### browser\n\nShould be included in the Webpack's config for browsers. It mocks some node modules that should not being used in browsers. See [here](https://github.com/facebookincubator/create-react-app/blob/aa322d0893dd0f789d4dbb7ff1878096c69edf1c/packages/react-scripts/config/webpack.config.prod.js#L357).\n\n### define\n\nCompile-time code replacement. See [DefinePlugin](https://webpack.js.org/plugins/define-plugin/).\n\n```javascript\ndefine(options)\n```\n\nParameters:\n\n- **options**: `object`\n  - **NODE_ENV**: `false|any`, defines `process.env.NODE_ENV`. `false` - `NODE_ENV` will not be defined, otherwise will set `NODE_ENV` to provided one. **default**: based on `env.production`, so if you need to define correct `NODE_ENV`, omit this key.\n  - **...defines**: `values`. Every key will be defined as `process.env.key` to it's value.\n  - **$prefix**: `string`, will be added to the every key as a prefix. It is not the best idea to override it, but it is possible. The prefix for **NODE_ENV** will still stay the default one. **default**: `'process.env.'`\n\n```javascript\ndefine({\n  NODE_ENV: 'test',\n  API_URL: 'http://api-provider.com/',\n})\n// in client code:\nconsole.log(process.env.NODE_ENV)\n// -\u003e will be transpiled to console.log('test')\nconsole.log(process.env.API_URL)\n// -\u003e console.log('http://api-provider.com/')\n```\n\n### externals\n\nAdd externals. Should be added to config for node to exclude `node_modules` from being bundled.\n\n```javascript\nexternals(options)\n```\n\nParameters:\n\n- **options**: `object`\n  - **react**: `boolean`, add react to externals. Usefull for libraries. **default**: `false`\n  - **list**: `array`, additional list of externals. **default**: `[]`\n  - **whitelist**: `array`, these entries will be bundled. **default**: `[/\\.(?!(?:jsx?|json)$).{1,5}$/i]` to bundle any non-JS files from `node_modules`\n  - **modulesDir**: `string`, path to `node_modules`. **default**: `node_modules`\n\n```javascript\nexternals({\n  react: true\n  list: [\n    {\n      lodash : {\n        commonjs: \"lodash\",\n        amd: \"lodash\",\n        root: \"_\" // indicates global variable\n      }\n    }\n  ]\n})\n```\n\n### optimization\n\nAdd optimizations for bundles: minimizing, code splitting.\n\n```javascript\noptimization(options)\n```\n\nParameters:\n\n- **options**: `object`\n  - **minimize**: `boolean`, minimize bundle code. **default**: `production`.\n  - **split**: `boolean`, should split code to `runtime`, `vendors`, `main` bundles. **default**: `true` for `browsers` target in `production` mode.\n\n```javascript\noptimizatione({\n  minimize: false,\n  split: true,\n})\n```\n```javascript\n// production browsers config\n\nconst webpack = require('webpack');\n\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst CleanWebpackPlugin = require('clean-webpack-plugin');\n\nconst createFeatures = require('webpack-features');\n\nconst root = ROOT_PATH;\nconst dist = DIST_PATH;\n\nconst publicPath = 'dist/';\n\nconst env = {\n  target: { browsers: 'legacy' },\n  production: true,\n  publicPath,\n};\n\nconst {\n  createConfig,\n  entry,\n  javascript,\n  styles,\n  production,\n  namedModules,\n  media,\n  emotion,\n} = createFeatures(env);\n\nmodule.exports = createConfig(\n  entry({ index: './src/client/index.js' }),\n  javascript(),\n  styles({\n    preprocessors: ['css'],\n    cssModules: 'both',\n  }),\n  emotion(),\n  media(),\n  {\n    output: {\n      path: dist,\n      publicPath,\n      filename: '[name].[chunkhash].js',\n      chunkFilename: '[name].[chunkhash].js',\n    },\n  },\n  {\n    plugins: [\n      new webpack.DefinePlugin({\n        'process.env.NODE_ENV': '\"production\"',\n      }),\n\n      new CleanWebpackPlugin(['static/dist'], {\n        root,\n      }),\n    ],\n  },\n  production(),\n  namedModules(),\n  {\n    plugins: [\n      new HtmlWebpackPlugin({\n        template: './src/client/index.html',\n        filename: '../index.html',\n      }),\n    ],\n  }\n);\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoviel%2Fwebpack-features","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoviel%2Fwebpack-features","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoviel%2Fwebpack-features/lists"}