最近和部门老大,一块儿在研究团队【EFT - 前端新手村】的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发而且达到公司业务开发水平。javascript
本文也是属于【EFT - 前端新手村】的一部分,用来帮助新人快速入门 Webpack4
,内容偏基础,固然也能够做为复习材料~~这里分享给各位小伙伴啦!css
我将从最基础的【项目初始化】开始介绍,到【处理 CSS / JS / 图片】,到【热更新,打包优化】等等,一一介绍和实践。html
文章共分为 18 章,关于最基础的四个核心概念,能够到我整理的另外一篇文章 《Webpack4 的四个核心概念》 中学习。前端
新建并进入文件夹 leo
:java
mkdir leo cd leo
而后本地安装 webpack
和 webpack-cli
(在 Webpack 4.0之后须要单独安装):node
npm install webpack webpack-cli --save-dev
初始化项目结构:jquery
+ ├─package.json + ├─dist // 存放最终打包的文件 + │ └─index.html + ├─src // 存放入口文件等开发文件 + │ └─index.js + ├─webpack.config.js // webpack的配置文件
安装 lodash
:webpack
npm install lodash --save-dev
--save
能够简写为-S
, --save-dev
能够简写为-D
.git
开发 index.js
:github
import _ from 'lodash'; function createElement(){ let div = document.createElement('div'); div.innerHTML = _.join(['my', 'name', 'is', 'leo'], ''); return div; } document.body.appendChild(createElement());
开发 webpack.config.js
:
const path = require('path'); module.exports = { entry: './src/index.js', mode: 'development', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') } }
开始第一次打包任务:
npx webpack // 输出: Hash: 030b37b6b9a0b4344437 Version: webpack 4.39.1Time: 308ms Built at: 2019-08-07 08:10:21 Asset Size Chunks Chunk Names main.js 552 KiB main [emitted] main Entrypoint main = main.js [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 225 bytes {main} [built] + 1 hidden module
打包成功后,生成的文件会保存在 dist
目录中。
如今在 dist/index.html
中引入打包后的 main.js
,打开浏览器测试:
<script src="./main.js"></script>
这一部分,咱们开始学着使用 webpack
去处理 css
相关的模块。
在项目 src
目录中,新建 style
文件夹,并新建 index.css
文件:
├─package.json ├─dist // 存放最终打包的文件 │ └─index.html ├─src // 存放入口文件等开发文件 │ ├─index.js + │ └─style + │ └─index.css ├─webpack.config.js // webpack的配置文件
接着在 index.js
的新建元素方法中,添加 class
为 box
,这样新建的元素就带有 box
的 class
属性:
// src/index.js import _ from 'lodash'; import './style/index.css';// 引入样式文件 function createElement(){ let div = document.createElement('div'); div.innerHTML = _.join(['my', 'name', 'is', 'leo'], ''); + div.className = 'box'; return div; } document.body.appendChild(createElement());
而后在 index.css
文件为 box
:
// src/style/index.css .box{ color: red; }
注意:
这里使用 import './style/index.css';
引入咱们的样式文件,是没办法解析使用,这时咱们须要在 webpack
中使用到第三方 loader
插件,这里咱们使用:
css-loader
: 用于处理 css
文件,使得能在 js 文件中引入使用;style-loader
: 用于将 css
文件注入到 index.html
中的 <style>
标签上;安装插件:
npm install --save-dev style-loader css-loader
再到 webpack.config.js
中添加 css
解析的 loader
配置:
// webpack.config.js module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"] } ] }
参数介绍:
test
:须要匹配的模块后缀名;
use
:对应处理的 loader 插件名称(处理顺序是从右往左)。
npx webpack // 输出: Hash: 28b3965aa1b6a0047536 Version: webpack 4.39.1 Time: 482msBuilt at: 2019-08-09 07:45:25 Asset Size Chunks Chunk Names main.js 565 KiB main [emitted] main Entrypoint main = main.js [./node_modules/_css-loader@3.2.0@css-loader/dist/cjs.js!./src/style/index.css] 190 bytes {main} [built] [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built][./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 303 bytes {main} [built] [./src/style/index.css] 447 bytes {main} [built] + 3 hidden modules
这时候能够看见 index.html
中,文本已经变成红色,而且 css
代码已经添加到 <style>
标签上。
在这一节中,咱们会介绍 webpack
中的模块,而且介绍如何去处理 sass
文件。
这里介绍的模块(module)是指 webpack.config.js
文件中的 module
配置,它决定了如何处理项目中的不一样类型模块。
好比上一节介绍的,使用 style-loader
、 css-loader
两个插件去处理 css
文件。
webpack
模块支持以下语句:
import
语句;require()
语句;define
和 require
语句;css/sass/less
文件中 @import
语句;(url(...))
或者 HTML 文件 (<img src=...>)
中的图片连接 (image url)
;这里建议使用 ES2015
的引入方法,毕竟这是标准。
更多参数介绍,可访问中文官网的介绍:
《webpack 配置选项》
值的类型:RegExp | [RegExp] | function
防止 webpack
解析那些符合匹配条件的文件,忽略的文件夹中不该该含有 import
、require
、define
的调用,或任何其余导入机制,忽略的 library
能够提升构建效率。
// webpack.config.js module: { noParse: function(content){ return /jquery|lodash/.test(content); } }
建立模块时,匹配请求的规则数组。按照规则为对应模块使用对应的 loader
,或修改解析器(parser)。
// webpack.config.js module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader']} ] }
module.rules
参数有:use
:为模块使用指定 loader
,而且能够传入一个字符串数组,加载顺序从右往左。
module.rules
匹配条件有:{test : Condition}
:匹配特定条件,非必传,支持一个正则表达式或正则表达式数组;
{include : Condition}
:匹配特定条件,非必传,支持一个字符串或字符串数组;
{exclude : Condition}
:排除特定条件,非必传,支持一个字符串或字符串数组;
{and : [Condition]}
:必须匹配数组中的全部条件;
{or : [Condition]}
:匹配数组中任一条件;
{not : [Condition]}
:必须排除这个条件;
更多参数介绍,可访问中文官网的介绍:
《Rule》
// webpack.config.js module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'], include: [ path.resolve(__dirname, "app/style.css"), path.resolve(__dirname, "vendor/style.css") ] } ] }
须要使用到 sass-loader
的插件,这里先安装:
npm install sass-loader node-sass --save-dev
在 src/style
目录下添加 leo.scss
文件,并添加内容:
// leo.scss $bg-color: #ee3; .box{ background-color: $bg-color; }
而后在 src/index.js
中引入 leo.scss
文件:
// src/index.js import './style/leo.scss';
再 npx webpack
从新打包,并打开 dist/index.html
能够看到背景颜色已经添加上去:
[外链图片转存失败(img-eHBJzEHn-1565738603711)(https://user-gold-cdn.xitu.io/2019/8/12/16c868881e42f612?w=730&h=553&f=png&s=28540)]
像 npx webpack
这个命令咱们须要常用,对于这种命令,咱们能够把它写成命令,方便每次使用。
咱们在 package.json
的 scripts
中添加一个命令为 build
,之后打包只要执行 npm run build
便可:
"scripts": { "build": "npx webpack -c webpack.config.js" },
这里的 -c webpack.config.js
中,-c
后面跟着的是 webpack
配置文件的文件名,默承认以不写。
添加 SourceMap
是为了方便打包以后,咱们在项目中调试样式,定位到样式在源文件的位置。
在 css-loader
和 sass-loader
均可以经过设置 options
选项启用 sourceMap
。
// webpack.config.js rules: [ { test: /\.(sc|c|sa)ss$/, use: [ "style-loader", { loader:"css-loader", options:{ sourceMap: true } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ]
再从新打包,看下 index.html
的样式,样式已经定位到源文件上了:
[外链图片转存失败(img-2LKJpwyu-1565738603712)(https://user-gold-cdn.xitu.io/2019/8/12/16c86888236dd2d8?w=917&h=733&f=png&s=37584)]
这样咱们在开发过程当中,调试样式就方便不少了。
这里咱们用到 PostCSS
这个 loader
,它是一个 CSS 预处理工具,能够为 CSS3 的属性添加前缀,样式格式校验(stylelint
),提早使用 CSS
新特性,实现 CSS
模块化,防止 CSS
样式冲突。
首先安装 PostCSS
:
npm install postcss-loader autoprefixer --save-dev
另外还有:
postcss-cssnext
可让咱们使用 CSS4
的样式,并能配合 autoprefixer
进行浏览器部分兼容的补全,还支持嵌套语法。
precss
相似 scss
语法,若是咱们只须要使用嵌套,就能够用它替换 scss
。
postcss-import
让咱们能够在@import
CSS文件的时 webpack
能监听并编译。
更多参数介绍,可访问中文官网的介绍:
《postcss-loader》
开始添加 postcss-loader
并设置 autoprefixer
:
// webpack.config.js rules: [ { test: /\.(sc|c|sa)ss$/, use: [ "style-loader", { loader:"css-loader", options:{ sourceMap: true } }, { loader:"postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require('autoprefixer')(), // 这里可使用更多配置,如上面提到的 postcss-cssnext 等 // require('postcss-cssnext')() ] } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ]
还须要在 package.json
中添加判断浏览器版本:
// package.json { //... "browserslist": [ "> 1%", // 全球浏览器使用率大于1%,最新两个版本而且是IE8以上的浏览器,加前缀 "last 2 versions", "not ie <= 8" ] }
为了作测试,咱们修改 src/style/leo.scss
中 .box
的样式:
// src/style/leo.scss .box{ background-color: $bg-color; display: flex; }
而后从新打包,能够看见 CSS3 属性的前缀已经添加上去了:
在以前学习中,CSS 样式代码都是写到 index.html
的 <style>
标签中,这样样式代码多了之后,很不方便。
因而咱们须要将这些样式打包成单独的 CSS
文件。
webpack4 开始使用 mini-css-extract-plugin
插件,而在 1-3 版本使用 extract-text-webpack-plugin
。
注意:抽取样式之后,就不能使用
style-loader
注入到 html 中。
安装插件:
npm install mini-css-extract-plugin --save-dev
引入插件:
// webpack.config.js const MiniCssExtractPlugin = require('mini-css-extract-plugin');
而后修改 rules
,将 style-loader
,替换成 MiniCssExtractPlugin.loader
,而后添加 plugins
配置项:
// webpack.config.js module: { rules: [ { test: /\.(sc|c|sa)ss$/, use: [ MiniCssExtractPlugin.loader, { loader:"css-loader", options:{ sourceMap: true } }, { loader:"postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [require('autoprefixer')()] } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css', // 最终输出的文件名 chunkFilename: '[id].css' }) ]
而后从新打包,这时候能够看到咱们 dist
目录下就多了个 main.css
文件:
[外链图片转存失败(img-3juocHi2-1565738603713)(https://user-gold-cdn.xitu.io/2019/8/12/16c86888174082f4?w=320&h=384&f=png&s=13495)]
由于如今已经将 CSS 都抽取成单独文件,因此在 dist/index.html
中,咱们须要手动引入 main.css
了:
// index.html
<link rel="stylesheet" href="main.css">
为了缩小打包后包的体积,咱们常常作优化的时候,将 CSS 和 JS 文件进行压缩,这里须要使用到不一样的插件。
使用 optimize-css-assets-webpack-plugin
压缩 CSS 的插件。
安装插件:
npm install optimize-css-assets-webpack-plugin --save-dev
使用插件:
// webpack.config.js // ... 省略 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); module.exports = { // ... 省略 plugins: [ // ... 省略 new OptimizeCssAssetsPlugin({}) ], }
从新打包,能够看到 main.css
已经被压缩成一行代码,即压缩成功~
使用 uglifyjs-webpack-plugin
压缩 JS 的插件。
安装插件:
npm install uglifyjs-webpack-plugin --save-dev
引入插件:
// webpack.config.js const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
使用插件:
// webpack.config.js // ... 省略 module.exports = { // ... 省略 plugins: [ // ... 省略 new OptimizeCssAssetsPlugin({}), new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }) ], }
其中 UglifyJsPlugin
的参数:
cache
:当 JS 没有发生变化则不压缩;
parallel
:是否启用并行压缩;
sourceMap
:是否启用 sourceMap;
而后从新打包,查看 main.js
,已经被压缩了:
因为咱们打包出来的 css
、js
文件是静态文件,就存在缓存问题,所以咱们能够给文件名添加 hash
值,防止缓存。
直接在 webpack.config.js
中,为须要添加 hash 值的文件名添加 [hash]
就能够:
// webpack.config.js module.exports = { // ... 省略其余 output: { filename: 'main.[hash].js', path: path.resolve(__dirname, 'dist') }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].[hash].css', chunkFilename: '[id].[hash].css' }), ], }
配置完成后,从新打包,就能够看到文件名中包含了 hash
值了:
因为咱们前面给打包的文件名添加了 hash
值,会致使 index.html
引用文件错误,因此咱们须要让它能动态引入打包后的文件。
这里咱们使用 HtmlWebpackPlugin
插件,它能够把打包后的 CSS 或者 JS 文件直接引用注入到 HTML 模版中,就不用每次手动修改。
安装插件:
npm install html-webpack-plugin --save-dev
引入插件:
// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin');
使用插件:
// webpack.config.js plugins: [ new HtmlWebpackPlugin({ title: "leo study!", // 生成的文件标题 filename: "main.html", // 最终生成的文件名 minify: { // 压缩选项 collapseWhitespace: true, // 移除空格 removeComments: true, // 移除注释 removeAttributeQuotes: true, // 移除双引号 } }) ],
关于 html-webpack-plugin
更多介绍能够《查看文档》https://github.com/jantimon/html-webpack-plugin/。
接着咱们打包之后,能够看见 dist
目录下,多了 main.html
的文件,格式化之后,能够看出,已经动态引入打包后的 CSS 文件和 JS 文件了:
在以前,咱们每次打包都会生成新的文件,而且在添加 hash
值之后,文件名不会出现重复的状况,致使旧文件的冗余。
为了解决这个问题,咱们须要在每次打包以前,将 /dist
目录清空,再进行打包。
这里咱们使用 clean-webpack-plugin
插件来实现。
安装插件:
npm install clean-webpack-plugin --save-dev
引入插件:
// webpack.config.js const CleanWebpackPlugin = require('clean-webpack-plugin');
使用插件:
// webpack.config.js plugins: [ new CleanWebpackPlugin() ],
参数 cleanOnceBeforeBuildPatterns
是表示须要清除的文件夹。
这样咱们每次打包以前,都会先将 /dist
目录清空一次,再执行打包。
更多参数介绍,可访问中文官网的介绍:
《clean-webpack-plugin》
在项目中引入图片:
// src/style/leo.scss .box{ background-color: $bg-color; display: flex; background: url('./../assets/logo.jpg') }
这时候咱们若是直接打包,会报错。
咱们须要使用 file-loader
插件来处理文件导入的问题。
安装插件:
npm install file-loader --save-dev
使用插件:
// webpack.config.js module: { { test: /\.(png|svg|jpg|jpeg|gif)$/, use: ["file-loader"] }] },
从新打包之后,发现 dist
目录下多了一个如 373e5e0e214390f8aa9e7abb4c7c635c.jpg
名称的文件,这就是咱们打包后的图片。
更进一步,咱们能够对图片进行压缩和优化,这里咱们用到 image-webpack-loader
插件来处理。
安装插件:
npm install image-webpack-loader --save-dev
使用插件:
// webpack.config.js module: { { test: /\.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, 'src/')], use: ["file-loader",{ loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: '65-90', speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }, ] }] },
更多参数介绍,可访问中文官网的介绍:
《image-webpack-loader》
再从新打包,咱们能够看到图片打包先后,压缩了很大:
url-loader
功能相似于 file-loader
,能够将 url 地址对应的文件,打包成 base64 的 DataURL,提升访问效率。
安装插件:
npm install url-loader --save-dev
使用插件:
注意:这里须要将前面配置的
image-webpack-loader
先删除掉,在使用url-loader
。
// webpack.config.js module: { { test: /\.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, 'src/')], use: [ { loader: 'url-loader', // 根据图片大小,把图片转换成 base64 options: { limit: 10000 }, }, { loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: '65-90', speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }, ] }] },
更多参数介绍,可访问中文官网的介绍:
《url-loader》
字体处理的方式和图片处理方式是同样的,只是咱们在配置 rules
时的 test
值不相同:
// webpack.config.js module: { { test: /\.(woff|woff2|eot|ttf|otf)$/, include: [path.resolve(__dirname, 'src/')], use: [ 'file-loader' ] } },
在开发环境(development)和生产环境(production)配置文件有不少不一样,但也有部分相同,为了避免每次更换环境的时候都修改配置,咱们就须要将配置文件作合并,和提取公共配置。
咱们使用 webpack-merge
工具,将两份配置文件合并。
安装插件:
npm install webpack-merge --save-dev
而后调整目录结构,为了方便,咱们将原来 webpack.config.js
文件修更名称为 webpack.commen.js
,并复制两份相同的文件出来,分别修改文件名为 webpack.prod.js
和 webpack.dev.js
。
├─package.json ├─dist ├─src - ├─webpack.config.js + ├─webpack.common.js // webpack 公共配置文件 + ├─webpack.prod.js // webpack 生产环境配置文件 + ├─webpack.dev.js // webpack 开发环境配置文件
因为咱们文件调整了,因此在 package.json
中,打包命令也须要调整,而且配置 mode
模式。
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "npx webpack -c webpack.config.js", + "build": "npx webpack -c webpack.dev.js --mode development", + "dist": "npx webpack -c webpack.prod.js --mode production" },
咱们先调整 webpack.common.js
文件,将通用的配置保留,不是通用的配置删除,结果以下:
// webpack.common.js const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: './src/index.js', module: { noParse: function (content) {return /jquery|lodash/.test(content);}, rules: [ { test: /\.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, 'src/')], use: [{ loader: 'url-loader', // 根据图片大小,把图片转换成 base64 options: { limit: 10000 }, },{ loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: '65-90', speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }] },{ test: /\.(woff|woff2|eot|ttf|otf)$/, include: [path.resolve(__dirname, 'src/')], use: [ 'file-loader' ] }] }, plugins: [ new HtmlWebpackPlugin({ title: "leo study!", filename: "main.html", template: path.resolve(__dirname, 'src/index.html'), minify: { collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, } }), new CleanWebpackPlugin() ], }
安装 babel-loader
是为了将 ES6 及以上版本的 JS 代码转换成 ES5。
npm install babel-loader @babel/core @babel/preset-env --save-dev
使用插件:
// webpack.common.js rules: [ // ... 省略其余 { test: /\.js$/, use: [{ loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } }], exclude: /(node_modules|bower_components)/, } ]
关于 babel-loader
更多介绍能够《查看文档》https://webpack.js.org/loaders/babel-loader/。
这里咱们就须要用到 merge-webpack
插件进行配置合并了:
// webpack.dev.js const path = require('path'); const merge = require('webpack-merge'); const common = require('./webpack.common.js'); let devConfig = { mode: 'development', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [{ test: /\.(sc|c|sa)ss$/, use: [ 'style-loader', { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require('autoprefixer')() ] } }, { loader: "sass-loader", options: { sourceMap: true } } ] }] } } module.exports = merge(common, devConfig)
一样对于生产环境的配置,咱们也须要用 merge-webpack
插件进行配置合并:
// webpack.prod.js const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const merge = require('webpack-merge'); const common = require('./webpack.common.js'); let prodConfig = { mode: 'production', output: { filename: 'main.[hash].js', path: path.resolve(__dirname, 'dist') }, module: { rules: [{ test: /\.(sc|c|sa)ss$/, use: [ MiniCssExtractPlugin.loader, { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require('autoprefixer')() ] } }, { loader: "sass-loader", options: { sourceMap: true } } ] }] }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].[hash].css', chunkFilename: '[id].[hash].css' }), new OptimizeCssAssetsPlugin({}), new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }), ], } module.exports = merge(common, prodConfig)
当 webpack 打包源代码后,就很难追踪到错误和警告在源代码的位置。
如将三个源文件打包一个 bundle
中,其中一个文件的代码报错,那么堆栈追中就会指向 bundle
。
为了能方便定位错误,咱们使用 inline-source-map
选项,注意不要在生产环境中使用。
// webpack.dev.js let devConfig = { // ... 省略其余 + devtool: 'inline-source-map' }
为了测试是否成功,咱们将 src/index.js
代码中,在第 12 行上,添加一句日志打印。
// src/index.js // ... 省略其余 + console.log(111)
对比下开启 sourceMap
先后的区别:
若是每次咱们修改完代码,都要手动编译,那是多累的一件事。
为此咱们使用 --watch
命令,让咱们每次保存完,都会自动编译。
为此,咱们须要在 package.json
中的打包命令添加 --watch
命令:
// package.json - "build": "npx webpack --config webpack.dev.js", + "build": "npx webpack --config webpack.dev.js --watch",
这里仅对开发环境开启,生产环境不须要使用。
上一节介绍监控自动编译,当咱们保存文件后,会自动编译文件,可是咱们仍是须要手动去刷新页面,才能看到编译后的结果。
因而为了自动编译以后,再自动从新加载,咱们就可使用 webpack-dev-server
来启动一个简单 web 服务器,实时从新加载。
插件安装:
npm install webpack-dev-server --save-dev
使用插件:
// webpack.dev.js const webpack = require('webpack'); const webpack = require('webpack'); let devConfig = { // ... 省略其余 devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, hot: true, overlay: true, open:true, publicPath: '/', host: 'localhost', port: '1200' } plugins: [ new webpack.NamedModulesPlugin(), // 更容易查看(patch)的以来 new webpack.HotModuleReplacementPlugin() // 替换插件 ] }
启动热更新:
npx webpack-dev-server --config webpack.dev.js
经常使用配置:
contentBase: path.join(__dirname, 'dist'), //本地服务器所加载的页面所在的目录 clinetLogLevel: 'warning', // 可能值有 none, error, warning 或者 info (默认值) hot:true,//启动热更新替换特性,须要配合 webpack.HotModuleReplacementPlugin 插件 host:'0.0.0.0', // 启动服务器的 host port:7000, // 端口号 compress:true, // 为全部服务启用gzip压缩 overlay: true, // 在浏览器中显示全屏覆盖 stats: "errors-only" ,// 只显示包中的错误 open:true, // 启用“打开”后,dev服务器将打开浏览器。 proxy: { // 设置代理 "/api": { target: "http://localhost:3000", pathRewrite: {"^/api" : ""} } }
这时候咱们访问 http://localhost:1200/main.html
就能够看到页面,而且修改文件,页面也会同时刷新。
咱们能够将 npx webpack-dev-server --config webpack.dev.js
写到 package.json
中做为一个命令:
// package.json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "npx webpack --config webpack.dev.js --watch", "dist": "npx webpack --config webpack.prod.js", + "watch": "npx webpack-dev-server --config webpack.dev.js" },
接着上一节,接下来给 webpack 设置代理服务器:
// webpack.dev.js let devConfig = { // ... 省略其余 devServer: { // ... 省略其余 proxy: { "/api": { // 以 '/api' 开头的请求,会跳转到下面的 target 配置 target: "http://192.168.30.33:8080", pathRewrite: { "^api": "/mock/api" } } } }
最后当咱们请求 /api/getuser
接口,就会转发到 http://192.168.30.33:8080/mock/api
。
babel-loader
插件的安装,已经提早介绍,在【11、 webpack 配置合并和提取公共配置】中。
这里讲一下 babel-loader
的优化。
babel-loader
能够配置 cacheDirectory
来提升打包效率:
cacheDirectory
:默认值 false
,开启后构建时会缓存文件夹,后续从缓存中读取,将提升打包效率。安装插件:
npm install eslint eslint-loader --save-dev
另外还须要安装 eslint 解释器、校验规则等:
npm install babel-loader standard --save-dev
在项目根目录建立 .eslintrc.js
,指定 eslint 规则。
这份配置内容有点多,能够去 个人 gist 复制https://gist.github.com/pingan8787/8b9abe4e04bed85f9d7846e513ed2e11 。
在项目根目录建立 .eslintignore
,指定 eslint 忽略一些文件不校验,好比内容能够是:
/dist/ /node_modules/
在 webpack 配置中,咱们使用 resolve
来配置模块解析方式。
这是很是重要的,好比 import _ from 'lodash'
,实际上是加载解析了 lodash.js
文件。
该配置就是用来设置加载和解析的方式。
在解析过程当中,咱们能够进行配置:
当咱们引入一些文件时,须要写很长的路径,这样使得代码更加复杂。
为此咱们可使用 resolve.alias
,建立 import
或 require
的别名,使模块引入更加简单。
使用配置:
// webpack.common.js module.exports = { entry: './src/index.js', + resolve: { + alias: { + '@' : path.resolve(__dirname, 'src/') + } + } // 省略其余 }
alias
参数的含义:
使用 @
来替代 path.resolve(__dirname, 'src/')
这个路径,接下来咱们测试看看。
咱们在 src/
目录下新增 leo.js
:
// leo.js export let name = 'pingan';
再到 src/index.js
中引入:
// index.js import { name } from '@/leo.js';
这样就能正常引入。
固然,咱们也能够根据实际状况,为不一样路径设置不一样别名:
// webpack.common.js alias: { '@' : path.resolve(__dirname, 'src/') + 'assets' : path.resolve(__dirname, 'src/assets/') }
更多参数介绍,可访问中文官网的介绍:
《resolve》
resolve.extensions
用来自动解析肯定的扩展,让咱们在引入模块的时候,能够不用设置拓展名,默认值为:
extensions: [".js", ".json"]
使用配置:
// webpack.common.js import { name } from '@/leo';
当咱们使用 CDN 引入 jquery
时,咱们并不想把它也打包到项目中,咱们就能够配置 externals
外部拓展的选项,来将这些不须要打包的模块从输出的 bundle 中排除:
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
配置 externals
:
// webpack.common.js module.exports = { // ... 省略其余 + externals: { + jquery: 'jQuery' + }, }
经过上面配置,咱们就不会把不须要打包的模块打包进来。而且下面代码正常运行:
import $ from 'jquery'; $('.leo').show();
更多参数介绍,可访问中文官网的介绍:
《externals》
这里咱们使用 webpack-bundle-analyzer
插件,来对打包后的文件进行数据分析,历来找到项目优化的方向。
webpack-bundle-analyzer
使用交互式可缩放树形图可视化 webpack 输出文件的大小。
安装插件:
npm install webpack-bundle-analyzer --save-dev
这个咱们只有在开发环境中使用。
使用插件:
// webpack.dev.js const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() // ... ] }
配置完成之后,咱们执行 npm run build
打包,打包完成后,会自动打开一个数据报表分析的页面,地址是 http://127.0.0.1:8888/
:
[外链图片转存失败(img-IH7Ai82l-1565738603715)(https://user-gold-cdn.xitu.io/2019/8/12/16c86888dd548ee5?w=1433&h=715&f=png&s=48595)]
webpack-bundle-analyzer
将帮助咱们:
咱们常常将报表中区域最大的模块进行优化!
[外链图片转存失败(img-hD4VmaUv-1565738603716)(https://user-gold-cdn.xitu.io/2019/8/12/16c86888dd548ee5?w=1433&h=715&f=png&s=48595)]
咱们能够看出,打包后的项目中 lodash.js
占了很是大的内存,咱们就针对 lodash.js
进行优化。
咱们将 lodash.js
改成 CDN 引入:
// index.html <script src="https://cdn.bootcss.com/lodash.js/4.17.15/lodash.js"></script>
而后去设置上一节讲到的 externals
:
// webpack.common.js externals: { jquery: 'jQuery', + lodash: '_' },
再打包之后,能够看到 lodash.js
已经不在包里面了:
而且打包后的文件,也能正常运行:
[外链图片转存失败(img-Do0XZ0Ho-1565738603716)(https://user-gold-cdn.xitu.io/2019/8/12/16c86888e575e56a?w=661&h=610&f=png&s=18762)]
更多参数介绍,可访问中文官网的介绍:
《webpack-bundle-analyzer》
本文是根据 《2019最新Webpack4.0教程4.x 成仙之路》 学习总结下来的学习之路,适合入门,涉及范围较多,内容比较长,须要能静下心来学习。
内容若是有误,欢迎留言指点,我会及时修改。
本文代码最终托管在个人 github 上,点击查看(https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Webpack/introduction/README.md)。
但愿本身的文章会对各位有所帮助,也欢迎各位大佬指点。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | https://github.com/pingan8787/Leo_Reading/issues |
ES小册 | js.pingan8787.com |