安装 全局安装(不推荐) 1 npm install webpack webpack-cli -g
全局的话容易发生webpack3和webpack4的版本冲突
局部安装(推荐) 1 2 npm install webpack webpack-cli -D
查看版本
查看包版本
配置 项目目录文件下新建
webpack.config.js
entry & output webpack.config.js
1 2 3 4 5 6 7 8 module .exports = { mode :'development' , entry : './src/index.js' , output : { filename : 'bundle.js' , path : path.resolve (__dirname, 'bundle' ) } }
多入口 1 2 3 4 5 6 7 8 9 10 11 module .exports = { mode :'development' , entry : { main : './src/index.js' , sub : './src/index.js' } output : { filename : '[name].js' , path : path.resolve (__dirname, 'bundle' ) } }
浏览器缓存 1 2 3 4 5 6 7 8 9 10 11 12 13 14 module .exports = { mode :'development' , entry : './src/index.js' , optimization : { runtimeChunk : { name : 'runtime' } } output : { filename : '[name].[contenthash].js' , chunkFilename : '[name].[contenthash].chunk.js' , path : path.resolve (__dirname, '../dist' ) } }
publicPath 1 2 3 4 5 6 7 8 9 module .exports = { mode :'development' , entry : './src/index.js' , output : { publicPath : 'http://cdn.com.cn' , filename : 'bundle.js' , path : path.resolve (__dirname, 'bundle' ) } }
loader file-loader 说明 将文件上的import / require()解析为url,并将文件发送到输出目录中
安装 1 npm install file-loader -D
代码 webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module .exports = { module : { rules : [{ test : /\.(eot|ttf|svg|woff)$/ , use : { loader : 'file-loader' , options : { name : '[name]_[hash].[ext]' , outputPath : 'font/' } } }] } }
url-loader 说明 用于将文件转换为base64 URI
安装 1 npm install url-loader -D
代码 webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 module .exports = { module : { rules : [{ test : /\.(png|jpg|gif)$/ , use : { loader : 'url-loader' , options : { name : '[name]_[hash].[ext]' , outputPath : 'images/' , limit : 8192 } } }] } }
style-loader && css-loader 说明 style-loader通过注入标记将DOM添加到DOM
css-loader解释@ import和url(),如import / require()并解析它们。
安装 1 npm install style-loader css-loader -D
代码 webpack.config.js
1 2 3 4 5 6 7 8 module .exports = { module : { rules : [{ test : /\.css$/ , use : ['style-loader' , 'css-loader' ] }] } }
sass-loader && node-sass 说明 sass-loader加载Sass / SCSS文件并将其编译为CSS
node-loader是Node.js附加组件加载程序模块,用于增强需求。在enhanced-require中执行附加组件
安装 1 npm install sass-loader node-sass -D
代码 webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 module .exports = { module : { rules : [{ test : /\.scss$/ , use : [ 'style-loader' , 'css-loader' , 'sass-loader' ] }] } }
postcss-loader 说明 postcss-loader使用PostCSS处理CSS的webpack的加载器(产商前缀)
安装 1 npm install postcss-loader -D
代码 webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 module .exports = { module : { rules : [ { test : /\.scss$/ , use : [ 'style-loader' , 'css-loader' , 'postcss-loader' , 'sass-loader' ] }, { test : /\.css$/ , use : [ 'style-loader' , 'css-loader' , 'postcss-loader' ] }] } }
使用 1 npm install autoprefixer -D
项目目录下创建postcss.config.js
1 2 3 4 5 module .exports = { plugins : [ require ('autoprefixer' ) ] }
option: importLoaders importLoaders选项允许您在将css-loader应用于@imported资源之前配置多少个加载器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 module .exports = { module : { rules : [{ test : /\.scss$/ , use : [ 'style-loader' , { loader : 'css-loader' , options : { importLoaders : 2 , }, }, 'postcss-loader' , 'sass-loader' ] } ] } }
option: modules modules选项启用/禁用CSS模块规范并设置基本行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 module .exports = { module : { rules : [{ test : /\.scss$/ , use : [ 'style-loader' , { loader : 'css-loader' , options : { importLoaders : 2 , modules : true }, }, 'sass-loader' , 'postcss-loader' ] } ] } }
babel-loader Bebel 是一个工具链,主要用于将ECMAScript 2015+代码转换为当前和旧版浏览器或环境中的向后兼容版本的JavaScript。以下是Babel可以为您做的主要事情:
安装 1 npm install --save-dev babel-loader @babel/core
代码 1 2 3 4 5 6 7 8 9 10 module .exports = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" }] } }
在项目目录下新建.babelrc,相当如babel中options的配置项
preset-set 说明 preset-set 一个转化ES2015+的预设
安装 1 npm install @babel/preset-env --save-dev
代码 并在.babelrc下输入
1 2 3 { "presets" : ["@babel/preset-env" ] }
在webpack.config.js配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module .exports = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" , options : { presets : ["@babel/preset-env" ] } } ] } }
polyfill 说明 Polyfill 是一个js
库,主要抚平不同浏览器之间对js实现的差异
安装 1 npm install --save @babel/polyfill
使用 在业务代码中进行引入
1 import "@babel/polyfill" ;
问题 引入所有纠正由此带来代码臃肿
解决 在webpack.config.js键入以下内容以根据业务代码加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 module .exports = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" , options : { presets : [ ["@babel/preset-env" ,{ useBuiltIns : 'usage' }] ] } }] } }
warning 及 解决 WARNING: We noticed you’re using the useBuiltIns
option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the corejs
option.
1 npm install --save core-js@2
说明 plugin-transform-runtime 一个插件,可以重复使用Babel注入的帮助程序代码来节省代码
用于写类库代码而不污染全局变量
安装 1 2 3 npm install --save-dev @babel/plugin-transform-runtime npm install --save @babel/runtime npm install --save @babel/runtime-corejs2
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 module .exports = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" , options : { plugins : [["@babel/plugin-transform-runtime" ],{ "corejs" : 2 , "helpers" : true , "regenerator" : true , "useESModules" : false }] } }] } }
plugin html-webpack-plugin 安装 1 npm install html-webpack-plugin -D
说明 HtmlWebpackPlugin简化了HTML文件的创建,以便为您的webpack包提供服务。 这对于包含文件名中的哈希的webpack包特别有用,它会更改每个编译。 您可以让插件为您生成HTML文件,使用lodash模板提供您自己的模板,或使用您自己的加载器。
生成html并自动将output注入到htmlzhogn
代码 webpack.config.js
1 2 3 4 5 6 const HtmlWebpackPlugin = require ('html-webpack-plugin' )module .exports = { plugins : [new HtmlWebpackPlugin ({ template : 'src/html/index.html' })], }
说明 此插件将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。它支持CSS和SourceMaps的按需加载。
安装 1 npm install --save-dev mini-css-extract-plugin
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 const MiniCssExtractPlugin = require ('mini-css-extract-plugin' )module .exports = { module :{ rules : [ { test : /\.css$/ , use : [ MiniCssExtractPlugin .loader , 'css-loader' , 'postcss-loader' ] }, { test : /\.scss$/ , use : [ MiniCssExtractPlugin .loader , { loader : 'css-loader' , options : { importLoaders : 2 , modules : true }, }, 'postcss-loader' , 'sass-loader' ] } ] }, plugins : [ new MiniCssExtractPlugin ({ filename : '[name].css' , chunkFilename : '[name].chunk.css' }) ] }
防止tree shaking
package.json
1 2 3 4 5 { "sizeEffects" : [ "*.css" ] , }
workboxWebpackPlugin 说明 官方文档
Workbox provides two webpack plugins: one that generates a complete service worker for you and one that generates a list of assets to precache that is injected into a service worker file.
The plugins are implemented as two classes in the workbox-webpack-plugin
module, named GenerateSW
and InjectManifest
. The answers to the following questions can help you choose the right plugin and configuration to use.
用于在webpack中使用PWA
安装 1 npm install workbox-webpack-plugin -D
使用 1 2 3 4 5 6 7 8 const WorkboxWebpackPlugin = require ('workbox-webpack-plugin' );module .exports = { plugins : [ new WorkboxWebpackPlugin .GenerateSW ({ clientsClaim : true , skipWaiting : true })] }
测试 先安装http-server
1 npm install http-server -D
输入以启用服务
于http://localhost:8080/访问该服务
clean-webpack-plugin 安装 1 npm install clean-webpack-plugin -D
说明 非官方插件 ,用于清除制定目录文件下的内容
代码 1 2 3 4 5 6 const HtmlWebpackPlugin = require ('html-webpack-plugin' )module .exports = { plugins : [ new CleanWebpackPlugin () ], }
说明 此选项控制是否以及如何生成源映射。
代码 开发
1 2 3 4 module .exports = { mode :'development' , devtool : 'cheap-module-eval-source-map' , }
生产
1 2 3 4 module .exports = { mode :'production' , devtool : 'cheap-module-source-map' , }
WebpackDevServer 说明 webpack-dev-server可用于快速开发应用程序。请参阅开发指南以开始使用。
安装 1 npm install webpack-dev-server -D
执行
配置说明 devServer.contentBase告诉服务器从哪里提供内容。只有在您想要提供静态文件时才需要这样做
devServer.publicPath将用于确定应该从哪个服务器提供服务,并优先使用
devServer.proxy当您拥有单独的API后端开发服务器并且希望在同一域上发送API请求时,代理某些URL会很有用。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 module .exports = { devServer : { contentBase : './dist' , open : true , port : 8080 , proxy : { '/api' : { target : 'http://localhost:3000' , pathRewrite : {'^/api' : '' }, secure : false , bypass : function (req, res, proxyOptions ) { if (req.headers .accept .indexOf ('html' ) !== -1 ) { console .log ('Skipping proxy for browser request.' ); return '/index.html' ; } } } } } }
webpack-dev-middleware 可用于自启动一个webpack-dev-server
项目目录新建server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const express = require ('express' );const webpack = require ('webpack' );const webpackDevMiddleware = require ('webpack-dev-middleware' );const config = require ('./webpack.config.js' );const complier = webpack (config);const app = express ();app.use (webpackDevMiddleware (complier, { publicPath : config.output .publicPath })) app.listen (3000 , () => { console .log ('server is running' ); })
webpack.config.js中添加publicPath项
1 2 3 4 5 6 7 module .exports = { output : { publicPath : '/' , filename : '[name].js' , path : path.resolve (__dirname, 'dist' ) } }
执行
Hot Module Replacement 说明 hot启用webpack的热模块替换功能
hot在没有页面刷新的情况下启用热模块替换(请参阅devServer.hot)作为构建失败时的后备
代码 1 2 3 4 5 6 7 8 9 10 11 const webpack = require ('webpack' )module .exports = { devServer : { contentBase : './dist' , open : true , port : 8080 , hot : true , hotOnly : true , } plugins : [new webpack.HotModuleReplacementPlugin ()], }
optimization optimize-css-assets-webpack-plugin 说明 一个插件的WebPack优化\压缩CSS文件。
安装 1 npm install --save-dev optimize-css-assets-webpack-plugin
使用 1 2 3 4 5 6 const OptimizeCSSAssetsPlugin = require ('optimize-css-assets-webpack-plugin' );module .exports = { optimization : { minimizer : [new TerserJSPlugin ({}), new OptimizeCSSAssetsPlugin ({})], } }
UglifyjsWebpackPlugin 说明 这个插件使用uglify-js来缩小你的JavaScript。
安装 1 npm install uglifyjs-webpack-plugin -D
使用 1 2 3 4 5 6 7 const UglifyJsPlugin = require ('uglifyjs-webpack-plugin' );module .exports = { optimization : { minimizer : [new UglifyJsPlugin ()], }, };
Tree shaking 说明 Tree shaking用于JavaScript上下文中常用于消除死代码
Tree shaking只支持ES module的引入,即import,不支持require
mode: ‘production’自带Tree shaking
mode: ‘development’需要配置
代码 1 2 3 4 5 module .exports = { optimization : { usedExports : true }, }
package.json 中 sizeEffects 用于免于tree shaking的文件
1 2 3 4 { "sizeEffects" : false , }
Code Splitting 同步代码分割 需要在webpack.common.js中做optimization的配置
1 2 3 4 5 6 7 module .exports = { optimization : { splitChunks : { chunks : 'all' } } }
异步代码分割 不需要做任何配置,会自动进行代码分割,但是需要安装babel-plugin-dynamic-import-webpack进行ES6转化
babel-plugin-dynamic-import-webpack 说明 非官方
安装 1 npm install babel-plugin-dynamic-import-webpack -D
代码 .babelrc
1 2 3 { plugins: [ "dynamic-import-webpack" ] }
plugin-syntax-dynamic-import 说明 官方
安装 1 npm install --save-dev @babel/plugin-syntax-dynamic-import
代码 1 2 3 { "plugins" : [ "@babel/plugin-syntax-dynamic-import" ] }
SplitChunksPlugin 说明 使用前必须安装上述plugin-syntax-dynamic-import
最初,块(以及在其中导入的模块)通过内部webpack图中的父子关系进行连接。CommonsChunkPlugin用于避免跨越它们的重复依赖,但无法进一步优化。
代码 main.js
1 2 3 4 5 6 7 8 9 10 function getComponent ( ){ return import ('lodash' ).then (({default : _} )=> { var element = document .createElement ('div' ); element.innerHTML = _.join (['Dell' , 'Lee' ], '-' ); return element }) } getComponent ().then (element => { document .body .appendChild (element); })
webpack.common.js,同步的代码会读取到cacheGroups而异步的不会
1 2 3 4 5 6 7 8 9 10 11 module .exports = { optimization : { splitChunks : { chunks : 'all' , cacheGroups : { vendors : false , default : false } } } }
结果:会在dist目录单独生成lodash.js
配置同步代码和异步代码的加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 module .exports = { optimization : { splitChunks : { chunks : 'all' , minSize : 30000 , minChunks : 1 , maxAsyncRequests : 5 , maxInitialRequests : 3 , automaticNameDelimiter : '~' , name : true , cacheGroups : { vendors : { test : /[\\/]node_modules[\\/]/ , priority : -10 , }, default : { priority : -20 , reuseExistingChunk : true , filename : 'common.js' } } } } }
区分development和production打包 webpack-merge 安装 1 npm install webpack-merge -D
在文件目录下创建build文件夹
创建webpack.common.js、webpack.dev.js、webpack.prod.js
webpack.commom.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 const path = require ('path' )const HtmlWebpackPlugin = require ('html-webpack-plugin' )const CleanWebpackPlugin = require ('clean-webpack-plugin' )module .exports = { entry : './src/index.js' , module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , loader : "babel-loader" }, { test : /\.(png|jpg|gif)$/ , use : { loader : 'url-loader' , options : { name : '[name]_[hash].[ext]' , outputPath : 'images/' , limit : 8192 } } }, { test : /\.(eot|ttf|svg|woff)$/ , use : { loader : 'file-loader' } }, { test : /\.css$/ , use : [ 'style-loader' , 'css-loader' , 'postcss-loader' ] }, { test : /\.scss$/ , use : [ 'style-loader' , { loader : 'css-loader' , options : { importLoaders : 2 , modules : true }, }, 'postcss-loader' , 'sass-loader' ] } ] }, plugins : [ new HtmlWebpackPlugin ({ template : 'src/html/index.html' }), new CleanWebpackPlugin (), ], output : { filename : '[name].js' , path : path.resolve (__dirname, '../dist' ) } }
webpack.dev.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const webpack = require ('webpack' )const merge = require ('webpack-merge' )const commonConfig = require ('./webpack.common.js' )const devConfig = { mode : 'development' , devtool : 'cheap-module-eval-source-map' , devServer : { contentBase : './dist' , open : true , port : 8080 , hot : true , proxy : { '/api' : { target : 'http://localhost:3000' , pathRewrite : {'^/api' : '' } } } }, plugins : [ new webpack.HotModuleReplacementPlugin () ], optimization : { usedExports : true }, } module .exports = merge (commonConfig, devConfig)
webpack.prod.js 1 2 3 4 5 6 7 8 9 const merge = require ('webpack-merge' )const commonConfig = require ('./webpack.common.js' )const prodConfig = { mode : 'production' , devtool : 'cheap-module-source-map' , } module .exports = merge (commonConfig, prodConfig)
npm script dev && build package.json中
1 2 3 4 5 6 { "scripts" : { "dev" : "webpack-dev-server --config ./build/webpack.dev.js" , "build" : "webpack --config ./build/webpack.prod.js" } }
analyse 使用 参见官网
package.json中加入scripts
1 2 3 4 5 { "scripts" : { "analyse" : "webpack --profile --json > stats.json --config ./build/webpack.dev.js" } }
打开分析网站 或者webpack-chart ,将项目下生成的stat.json文件上传,更多分析工具看这里
Eslint 安装 1 2 npm install eslint -D npm install eslint-loader -D
快速初始化
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 module .exports = { module : { rules : [ { test : /\.js$/ , exclude : /node_modules/ , use : ["babel-loader" , { loader : 'eslint-loader' , options : { fix : true } }] } } }
git钩子做eslint 安装 1 npm install husky --save-dev
使用 package.json中
1 2 3 4 5 6 7 { "husky" : { "hooks" : { "pre-commit" : "npm run lint-fix" } } }
当执行commit的时候会先执行npm run lint-fix
其它 Preloading && Prefetching 说明 webpack推荐的一种代码分离异步加载的方式
使用 index.js
1 2 3 4 5 document .addEventListener ('click' , () => { import ( './js/click.js' ).then (({default : func} )=> { func (); }) })
click.js
1 2 3 4 5 6 7 function handleClick ( ){ const element = document .createElement ('div' ); element.innerHTML = 'Dell Lee' ; document .body .appendChild (element); } export default handleClick;