static module bundler, recursively build a dependency graph, package all into one or more bundles
Install:
- init project: npm init -y
- npm install --save-dev webpack
project:
- create "dist" dir or whatever output dir
- install the required packages : npm install --save xxx
- in html, only load the bundle
- in .js, use "import" or "require" to explicitly include dependency
- create "webpack.config.js"
- run: npx webpack
config:
npm scripts:
- in package.json, include under "scripts" "scripts":{"build":"webpack"}...
- start point of recursive search
- configure: entry:'.path/to/my/entry/file.js'
- where to emit bundles
- output: {path: ... , filename: 'my-bundle.js'}
- many configurable features
- enable process more than javascript files with type specific loaders
- enable use specific loaders such as babel-loader
- rules: an array of rule object
- test : identify which file or files should be transformed
- use : which loader to use to do the transforming
- include / exclude: specify path
- extra, powerful features
- require, then add
- var somePlugin = require('somePlugInIfNotBuiltIn');
- add
- plugins: [ new somePlugin({...}),...]
Supported expression of dependencies
- ES2015: import
- CommonJS: require()
- AMD: define & require
- css/sass/less: @import
- image in stylesheet (url()) or html (<img src=..)
Supported Module types
How modules are resolved, beyond reasonable defaults.
Create alias:
- alias : { AliasName : path.resolve(__dirname, 'src/alias-names/')
- then in code, can use "import Something from 'AliasName/something"
...... (ignoring not using functions)....
resolve.extensions:
- array of strings, defaults to [".js", ".json"]
- "*" for modules that are imported with their extension (import SomeFile from "./somefile.ext")
- is what enables users to leave off the extension when importing
resolve.modules:
- array of directories should be searched when resolving
- can resolve
- absolute file path
- relative path
- the dir of the resource file -> context
- module paths
- searched in all dir in resolve.modules
- can be configured with resolve.alias option
- can configure loader
- once resulved, if the target is
- folder
- contains package.json -> fields in resolv.mainFields looked up
- no package.json -> field in resolv.mainFields look up for a filename exists
- file
- if file has extension, bundle
- otherwise, resolve extension using resolve.extensions option
target : '...' -> allow specification of environment
- node : uses node.js like environment
- web :
so can pack for different environment. multiple targets allowed
... no need to worry unless use browser caching for performance optimization..
Development Environment & Hot Module Reload
Source map:
- devtool: 'inline-source-map', //- enable source map so debug tool can show correct source and line number
Watch Mode
- "scripts":{... "watch":"webpack --watch"}
- "npm run watch" command will not return, will watch file changes and automatically re-compiles
- need to refresh to see change
webpack-dev-server
- in webpack.config.js + devServer : { contentBase: './dist'},
- this tells webpack-dev-server the root dir (on localhost:8080)
- options for devServer
- host:"localhost"
- port: 3001
- historyApiFallback: true //?? what does this mean?
- hot:true //turn on hot model reload, see below
- in package.json +
- "start":"webpack-dev-server --open",
- run "npm run start"
- browser automatically reload after changed code compiled
- note: webpack-dev does NOT actually pack and create file output. if the files are needed, run webpack.
webpack-dev-middleware
- webpack-dev-server uses it internally
- can work with other server such as Express
- usage
- in webpack.config.js + publicPath:'/' in output:{}
- this publicPath will be used in server script as well, to make sure files served correctly
- in express server "server.js"
- https://webpack.js.org/guides/development/
- require config document, setup compiler webpack, use that and public path to init webpackDevMiddleware, then tell express app to use
- in package.json "scripts" + "server":"node server.js"
- now "npm run server"
- check output, see webpack works
Adjust Text Editor
- Disable "safe write" feature
- Sublime / IntelliJ / Vim / WebStorm
Hot Module Replacement (HMR)
Not means to use in production.
Reference:
For server (meaning: hot reload modules running in server):
- Allows modules updated at runtime without full server restart.
- TO enable
- in workpack.cofig JS
- entry point, +
- watch : true,
- target: "node",
- externals: [ nodeExternals({ whitelist: [ "webpack/hot/poll?1000" ] }) ],
- plugins: [ +
- new StartServerPlugin("server.js"), // ask webpack to start server directly
- new webpack.NamedModulesPlugin(), // help for information
- new webpack.HotModuleReplacementPlugin(),
- new webpack.NoEmitOnErrorsPlugin(),
- new webpack.DefinePlugin({"process.env": { BUILD_TARGET: JSON.stringify("server") }, }),
- output: { path: path.join(__dirname, ".build"), filename: "server.js" }, // generate the server script to start
- in starting up script (index.js the entry point)
- (see below) if module hot, add accepted hot modules and event listener.
- event listener can simply just output a message to console
- or, can remove previous app as listener and start listen again with current app
- the code looks weird but remember the module (app) is loaded "hot"