Webpack
lastmod 2025-02-14created 2016-04-0861 edits
A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows to load parts for the application on demand. Through "loaders," modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.
Categories
- Source Map
- Webpack:Loader
- Webpack:Plugin
Plugins
TypeScript - Type Declarations Plugins
-
declaration-bundler-webpack-plugin - webpack-plugin-typescript-declaration-bundler (Based on:
declaration-bundler-webpack-plugin) - typescript-declaration-webpack-plugin
Why use Webpack?
Here are some practical reasons to use Webpack.
- You can bundle js files into a single file.
- You can use npm packages in frontend code.
- You can write ES6/ES7 JavaScript code. (Using Babel)
- You can minify or optimize code.
- You can turn LESS/SCSS into CSS.
- You can use HMR (Hot Module Replacement).
- You can include any type of file through JavaScript.
- There are many more advanced features not covered in this article.
Why do you need these features?
- Bundling js files - You can write JavaScript as modules, so you don't have to write a separate<script>
tag for each file. (More than one js file can be configured if the situation calls for it)
- Using npm packages - npm is a huge ecosystem of open-source code on the Internet. It gives you the chance to store npm code, and you can pull in and use any frontend package you want.
- ES6/ES7 - Many added features make writing JavaScript more powerful and easier. Here is an introductory article.
- Code minification/optimization - Reduces the size of distributed files. Benefits include faster page loading.
- Turning LESS/SCSS into CSS - A better way to write CSS. Here is an introductory article.
- Using HMR - Improves productivity. The page refreshes automatically every time you save code. Really handy when you need to keep the page state up to date while writing code.
- Including any type of file through JavaScript - Reduces the number of extra build tools, and lets you use and modify files programmatically.
How to install
To use all of Webpack's features, install it globally:
But if you only need some of Webpack's features or its optimization plugins, install it locally:
webpack-cli
For convenience features such as generating config files, install the CLI version separately:
Usage:
| WARNING |
| Installation also installs the @webpack-cli/generators package, for which github reports a security error, so remove it after init. |
How to use
To run Webpack:
To have Webpack build automatically when files change:
To use a user-defined Webpack config file with a specific name:
Modules
The import and export statements were standardized in ES2015. They are supported in most browsers today, but some browsers do not recognize the new syntax. Don't worry, though: webpack supports them out of the box.
Behind the scenes, webpack actually "transpiles" the code so that older browsers can run it too. If you look at dist/main.js, you can see how webpack transpiles it. Very ingenious! Besides import and export, webpack supports various other module syntaxes. See Module API for details.
webpack does not change any code other than import and export statements. If you use other ES2015 features, you need to use Babel, via webpack's loader system, as a transpiler.
See JavaScript Module System for details. (Summarizes the differences between CommonJS, AMD, UMD, and more)
Library Project
- Compiling and bundling TypeScript libraries with Webpack
- My experience configuring webpack to distribute a JavaScript library
- Turning webpack modules into a library
Example webpack.config.js file:
{
entry: {
'my-lib': './src/index.ts',
'my-lib.min': './src/index.ts'
},
output: {
path: path.resolve(__dirname, '_bundles'),
filename: '[name].js',
libraryTarget: 'umd',
library: 'MyLib',
umdNamedDefine: true
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
devtool: 'source-map',
plugins: [
new webpack.optimize.UglifyJsPlugin({
minimize: true,
sourceMap: true,
include: /\.min\.js$/,
})
],
module: {
loaders: [{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/,
query: {
declaration: false,
}
}]
}
}
It is exported under the library name set in .output.library. So when using it directly from HTML5/JavaScript:
<script src="./dist/main.js"></script>
<script type="text/javascript">
let mylib;
window.onload = () => {
mylib = new MyLib.MyClass(document.getElementById('root'));
// USE `graph`
}
</script>
Loaders
Loader Features
Loaders have the following characteristics.
- Loaders can be chained. Each loader in the chain applies transformations to the processed resource. The chain is executed in reverse order. The first loader passes its result (the resource with transformations applied) to the next loader, and so on down the chain. Finally, webpack expects the last loader in the chain to return JavaScript.
- Loaders can be synchronous or asynchronous.
- Loaders run in Node.js and can do anything that is possible in Node.js.
- Loaders can be configured with an options object. (You can still set options using query parameters, but this is not recommended)
- Normal modules can export a main and a loader through package.json with a loader field.
- Plugins can give loaders more features.
- Loaders can emit additional arbitrary files.
Loaders let you customize the output through preprocessing. Users now have the flexibility to add compression, packaging, language translations, and much more fine-grained logic.
Loader execution order
As explained in #Loader Features above, the chain is executed in reverse order.
and
The two snippets above are functionally equivalent. They work as style(css(file)). Loaders run from right to left.
Importing Other Assets
Write the following in a type declaration file ending in *.d.ts, such as custom.d.ts:
Plusings
- DefinePlugin
- Replaces specific strings in the code being compiled with configured values.
- UglifyJsPlugin
- Applies obfuscation and minification.
- CopyWebpackPlugin
- Copies individual files or entire directories, which already exist, to the build directory.
Troubleshooting
caniuse-lite is outdated
Browserslist: caniuse-lite is outdated. Please run:
npx browserslist@latest --update-db
Why you should do it regularly:
https://github.com/browserslist/browserslist#browsers-data-updating
Module not found
-
React study, week 2 -
[npm No valid alias configuration in the 'browser' field - Review Nara] - Setting up Path Alias in Webpack, Typescript | by JongHyun PARK | Medium
If a module-not-found error like the following is printed:
ERROR in ./src/main.js
Module not found: Error: Can't resolve 'components/DoISuportIt' in '[absolute path to my repo]/src'
resolve 'components/DoISuportIt' in '[absolute path to my repo]/src'
Parsed request is a module
using description file: [absolute path to my repo]/package.json (relative path: ./src)
Field 'browser' doesn't contain a valid alias configuration
aliased with mapping 'components': '[absolute path to my repo]/src/components' to '[absolute path to my repo]/src/components/DoISuportIt'
using description file: [absolute path to my repo]/package.json (relative path: ./src)
Field 'browser' doesn't contain a valid alias configuration
after using description file: [absolute path to my repo]/package.json (relative path: ./src)
using description file: [absolute path to my repo]/package.json (relative path: ./src/components/DoISuportIt)
as directory
[absolute path to my repo]/src/components/DoISuportIt doesn't exist
no extension
Field 'browser' doesn't contain a valid alias configuration
[absolute path to my repo]/src/components/DoISuportIt doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
[absolute path to my repo]/src/components/DoISuportIt.js doesn't exist
.jsx
Field 'browser' doesn't contain a valid alias configuration
[absolute path to my repo]/src/components/DoISuportIt.jsx doesn't exist
[[absolute path to my repo]/src/components/DoISuportIt]
[[absolute path to my repo]/src/components/DoISuportIt]
[[absolute path to my repo]/src/components/DoISuportIt.js]
[[absolute path to my repo]/src/components/DoISuportIt.jsx]
Set the resolve.alias property in webpack.config.js:
const path = require("path");
// ...
module.exports = {
//...
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
modules: [path.resolve(__dirname, "src"), "node_modules"],
// path alias를 설정하는 부분
alias: {
"@Commons": path.resolve(__dirname, "ClientApp/Commons"),
"@Template": path.resolve(__dirname, "ClientApp/Views/Template"),
"@Images": path.resolve(__dirname, "ClientApp/Images"),
"@Config": path.resolve(__dirname, "ClientApp/Config"),
"@Contexts": path.resolve(__dirname, "ClientApp/Contexts"),
}
},
//...
}
Another variant
Errors like the following may be printed across files in node_modules:
ERROR in ./node_modules/crypto-js/index.js 4:805-831
Module not found: Error: Can't resolve './rabbit-legacy' in '/home/your/Project/answer-dev/api/node_modules/crypto-js'
@ ./lib/crypto.ts 1:0-35 3:9-15
@ ./lib/reccApiBase.ts 14:0-37 364:13-22 369:13-22
@ ./lib/reccApi.ts 23:0-40 72:2-13
@ ./lib/index.ts 1:0-32 2:15-22
35 errors have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
webpack 5.72.0 compiled with 35 errors in 4469 ms
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
In this case, check resolve.extensions in webpack.config.js. It lets you omit file extensions when importing.
ERR_PACKAGE_PATH_NOT_EXPORTED
The following error occurs in nextjs.
- wait compiling...
- error ./app/globals.scss.webpack[javascript/auto]!=!./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[3].oneOf[13].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[3].oneOf[13].use[3]!./node_modules/next/dist/build/webpack/loaders/resolve-url-loader/index.js??ruleSet[1].rules[3].oneOf[13].use[4]!./node_modules/next/dist/compiled/sass-loader/cjs.js??ruleSet[1].rules[3].oneOf[13].use[5]!./app/globals.scss
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './tailwind.plugin.yourui' is not defined by "exports" in /home/your/Project/your-web/node_modules/your-ui/package.json
Import trace for requested module:
./app/globals.scss.webpack[javascript/auto]!=!./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[3].oneOf[13].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[3].oneOf[13].use[3]!./node_modules/next/dist/build/webpack/loaders/resolve-url-loader/index.js??ruleSet[1].rules[3].oneOf[13].use[4]!./node_modules/next/dist/compiled/sass-loader/cjs.js??ruleSet[1].rules[3].oneOf[13].use[5]!./app/globals.scss
./app/globals.scss
The important part is the following line: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './tailwind.plugin.yourui' is not defined by "exports" in /home/your/Project/your-web/node_modules/your-ui/package.json
Add the subpath to the exports of that package.json file. In this case, I changed it as follows:
{
// ...
"exports": {
".": {
"import": "./dist/your-ui.es.js",
"require": "./dist/your-ui.umd.js"
},
"./tailwind.plugin": {
"require": "./tailwind.plugin.yourui.js"
}
},
// ...
}
See also
Favorite site
- webpack web site
- Github - webpack web site
- React JS, Babel, Webpack
- [Recommended] Basic concepts of webpack
- [Recommended] webpack, a JavaScript modularization tool
- Understanding the frontend development environment: webpack (basics)
Guide
- [Recommended] Webpack handbook
- [Recommended] Create the latest JavaScript web frontend development environment with Webpack and Babel 1 (Webpack, JavaScript, Babel)
- webpack practical guide
- Webpack2, introductory guide part 1
- Getting a grip on Webpack concepts
- [Recommended] (Webpack 2) Optimizing
- Building a trendy frontend development environment (2018): Webpack 4
- [Recommended] A beginner's guide to Webpack2 and module bundling
- [Recommended] The confusing parts of Webpack
- Webpack tutorial for beginners part 1 - Getting started with Webpack
- Webpack - The confusing parts
- Github - wiki - wonism/TIL - Using Webpack
- [Recommended] About webpack configuration options
Typescript
Compare
- Differences between Grunt or Gulp vs Webpack
- Grunt and Gulp, Build your project
- (Gruntjs) NPM vs. Bower vs. Browserify vs. Gulp vs. Grunt vs. Webpack
- Stackshare - Webpack vs. gulp vs. Grunt
- [Recommended] Webpack or Browserify & Gulp: Which Is Better?
References
-
Create_the_latest_JavaScript_web_frontend_development_environment_with_Webpack_and_Babel.pdf ↩
- @babel/preset-typescript
- Babel
- Babel-loader
- Bower
- Continuous Integration
- ESLint
- Eslint-import-resolver-webpack
- Eslint-loader
- Eslint-plugin-import
- Eslint-webpack-plugin
- Gulp
- IntelliJ IDEA
- JavaScript
- JavaScript Module System
- JavaScript:Libraries
- Jest
- Ncc
- Npm:Module
- Package management system
- Package.json
- Programming
- Source Map
- Ts-loader
- Turbopack
- TypeScript
- TypeScript:TypeDeclarations
- Vite
- Vue Loader
- Vue.js
- VueCLI:Plugins
- Web development
- Webpack-dev-server
- Webpack:Loader
- Workbox