介绍

1. 背景

最近和部门老大,一起在研究团队【EFT - 前端新手村】的建设,目的在于:帮助新人快速了解和融入公司团队帮助零基础新人学习和入门前端开发并且达到公司业务开发水平

本文也是属于【EFT - 前端新手村】的一部分,用来帮助新人快速入门 Webpack4,内容偏基础,当然也可以作为复习材料~~这里分享给各位小伙伴啦!

2. 文章概要

由于本文篇幅较长,将分为《Webpack4入门手册(上)(共 18 章)》和《Webpack4入门手册(下)(共 18 章)》两篇文章发布,请联系起来看~

我将从最基础的【项目初始化】开始介绍,到【处理 CSS / JS / 图片】,到【热更新,打包优化】等等,一一介绍和实践。

文章共分为 18 章,关于最基础的四个核心概念,可以到我整理的另一篇文章 《Webpack4 的四个核心概念》 中学习。

《Webpack4 的四个核心概念》 https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Webpack/guide/README.md

3. 教程目录

十、 webpack 图片 base64 和字体处理

1. 图片 base64 处理

url-loader 功能类似于 file-loader,可以将 url 地址对应的文件,打包成 base64 的 DataURL,提高访问效率。

安装插件:

  1. npm install url-loader --save-dev

使用插件:

注意:这里需要将前面配置的 image-webpack-loader 先删除掉,在使用 url-loader

  1. // webpack.config.js
  2. module: {
  3. {
  4. test: /\.(png|svg|jpg|jpeg|gif)$/,
  5. include: [path.resolve(__dirname, 'src/')],
  6. use: [
  7. {
  8. loader: 'url-loader', // 根据图片大小,把图片转换成 base64
  9. options: { limit: 10000 },
  10. },
  11. {
  12. loader: "image-webpack-loader",
  13. options: {
  14. mozjpeg: { progressive: true, quality: 65 },
  15. optipng: { enabled: false },
  16. pngquant: { quality: '65-90', speed: 4 },
  17. gifsicle: { interlaced: false },
  18. webp: { quality: 75 }
  19. }
  20. },
  21. ]
  22. }]
  23. },

更多参数介绍,可访问中文官网的介绍:

2. 字体处理

字体处理的方式和图片处理方式是一样的,只是我们在配置 rules 时的 test 值不相同:

  1. // webpack.config.js
  2. module: {
  3. {
  4. test: /\.(woff|woff2|eot|ttf|otf)$/,
  5. include: [path.resolve(__dirname, 'src/')],
  6. use: [ 'file-loader' ]
  7. }
  8. },

十一、 webpack 配置合并和提取公共配置

在开发环境(development)和生产环境(production)配置文件有很多不同,但也有部分相同,为了不每次更换环境的时候都修改配置,我们就需要将配置文件做合并,和提取公共配置。

我们使用 webpack-merge 工具,将两份配置文件合并。

安装插件:

  1. npm install webpack-merge --save-dev

然后调整目录结构,为了方便,我们将原来 webpack.config.js 文件修改名称为 webpack.commen.js,并复制两份相同的文件出来,分别修改文件名为 webpack.prod.js 和 webpack.dev.js 。

  1. ├─package.json
  2. ├─dist
  3. ├─src
  4. - ├─webpack.config.js
  5. + ├─webpack.common.js // webpack 公共配置文件
  6. + ├─webpack.prod.js // webpack 生产环境配置文件
  7. + ├─webpack.dev.js // webpack 开发环境配置文件

由于我们文件调整了,所以在 package.json 中,打包命令也需要调整,并且配置 mode 模式。

  1. "scripts": {
  2. "test": "echo \"Error: no test specified\" && exit 1",
  3. - "build": "npx webpack -c webpack.config.js",
  4. + "build": "npx webpack -c webpack.dev.js --mode development",
  5. + "dist": "npx webpack -c webpack.prod.js --mode production"
  6. },

1. 调整 webpack.common.js

我们先调整 webpack.common.js 文件,将通用的配置保留,不是通用的配置删除,结果如下:

  1. // webpack.common.js
  2. const path = require('path');
  3. const HtmlWebpackPlugin = require('html-webpack-plugin');
  4. const { CleanWebpackPlugin } = require('clean-webpack-plugin');
  5. module.exports = {
  6. entry: './src/index.js',
  7. module: {
  8. noParse: function (content) {return /jquery|lodash/.test(content);},
  9. rules: [
  10. {
  11. test: /\.(png|svg|jpg|jpeg|gif)$/,
  12. include: [path.resolve(__dirname, 'src/')],
  13. use: [{
  14. loader: 'url-loader', // 根据图片大小,把图片转换成 base64
  15. options: { limit: 10000 },
  16. },{
  17. loader: "image-webpack-loader",
  18. options: {
  19. mozjpeg: { progressive: true, quality: 65 },
  20. optipng: { enabled: false },
  21. pngquant: { quality: '65-90', speed: 4 },
  22. gifsicle: { interlaced: false },
  23. webp: { quality: 75 }
  24. }
  25. }]
  26. },{
  27. test: /\.(woff|woff2|eot|ttf|otf)$/,
  28. include: [path.resolve(__dirname, 'src/')],
  29. use: [ 'file-loader' ]
  30. }]
  31. },
  32. plugins: [
  33. new HtmlWebpackPlugin({
  34. title: "leo study!",
  35. filename: "main.html",
  36. template: path.resolve(__dirname, 'src/index.html'),
  37. minify: {
  38. collapseWhitespace: true,
  39. removeComments: true,
  40. removeAttributeQuotes: true,
  41. }
  42. }),
  43. new CleanWebpackPlugin()
  44. ],
  45. }

2. 安装 babel-loader

安装 babel-loader 是为了将 ES6 及以上版本的 JS 代码转换成 ES5。

  1. npm install babel-loader @babel/core @babel/preset-env --save-dev

使用插件:

  1. // webpack.common.js
  2. rules: [
  3. // ... 省略其他
  4. {
  5. test: /\.js$/,
  6. use: [{
  7. loader: 'babel-loader',
  8. options: {
  9. presets: ['@babel/preset-env']
  10. }
  11. }],
  12. exclude: /(node_modules|bower_components)/,
  13. }
  14. ]

关于 babel-loader 更多介绍可以《查看文档》https://webpack.js.org/loaders/babel-loader/。

3. 调整 webpack.dev.js

这里我们就需要用到 merge-webpack 插件进行配置合并了:

  1. // webpack.dev.js
  2. const path = require('path');
  3. const merge = require('webpack-merge');
  4. const common = require('./webpack.common.js');
  5. let devConfig = {
  6. mode: 'development',
  7. output: {
  8. filename: 'main.js',
  9. path: path.resolve(__dirname, 'dist')
  10. },
  11. module: {
  12. rules: [{
  13. test: /\.(sc|c|sa)ss$/,
  14. use: [
  15. 'style-loader', {
  16. loader: "css-loader",
  17. options: { sourceMap: true }
  18. }, {
  19. loader: "postcss-loader",
  20. options: {
  21. ident: "postcss", sourceMap: true,
  22. plugins: loader => [ require('autoprefixer')() ]
  23. }
  24. }, {
  25. loader: "sass-loader",
  26. options: { sourceMap: true }
  27. }
  28. ]
  29. }]
  30. }
  31. }
  32. module.exports = merge(common, devConfig)

4. 调整 webpack.prod.js

同样对于生产环境的配置,我们也需要用 merge-webpack 插件进行配置合并:

  1. // webpack.prod.js
  2. const path = require('path');
  3. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  4. const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  5. const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  6. const merge = require('webpack-merge');
  7. const common = require('./webpack.common.js');
  8. let prodConfig = {
  9. mode: 'production',
  10. output: {
  11. filename: 'main.[hash].js',
  12. path: path.resolve(__dirname, 'dist')
  13. },
  14. module: {
  15. rules: [{
  16. test: /\.(sc|c|sa)ss$/,
  17. use: [
  18. MiniCssExtractPlugin.loader, {
  19. loader: "css-loader",
  20. options: { sourceMap: true }
  21. }, {
  22. loader: "postcss-loader",
  23. options: {
  24. ident: "postcss", sourceMap: true,
  25. plugins: loader => [ require('autoprefixer')() ]
  26. }
  27. }, {
  28. loader: "sass-loader",
  29. options: { sourceMap: true }
  30. }
  31. ]
  32. }]
  33. },
  34. plugins: [
  35. new MiniCssExtractPlugin({
  36. filename: '[name].[hash].css',
  37. chunkFilename: '[id].[hash].css'
  38. }),
  39. new OptimizeCssAssetsPlugin({}),
  40. new UglifyJsPlugin({
  41. cache: true, parallel: true, sourceMap: true
  42. }),
  43. ],
  44. }
  45. module.exports = merge(common, prodConfig)

十二、 webpack 监控自动编译和启用 js 的 sourceMap

1. 开启 js 的 sourceMap

当 webpack 打包源代码后,就很难追踪到错误和警告在源代码的位置。

如将三个源文件打包一个 bundle 中,其中一个文件的代码报错,那么堆栈追中就会指向 bundle

为了能方便定位错误,我们使用 inline-source-map 选项,注意不要在生产环境中使用。

  1. // webpack.dev.js
  2. let devConfig = {
  3. // ... 省略其他
  4. + devtool: 'inline-source-map'
  5. }

2. 测试 sourceMap

为了测试是否成功,我们将 src/index.js 代码中,在第 12 行上,添加一句日志打印。

  1. // src/index.js
  2. // ... 省略其他
  3. + console.log(111)

对比下开启 sourceMap 前后的区别:

3. 开启监控自动编译

如果每次我们修改完代码,都要手动编译,那是多累的一件事。

为此我们使用 --watch 命令,让我们每次保存完,都会自动编译。

为此,我们需要在 package.json 中的打包命令添加 --watch 命令:

  1. // package.json
  2. - "build": "npx webpack --config webpack.dev.js",
  3. + "build": "npx webpack --config webpack.dev.js --watch",

这里仅对开发环境开启,生产环境不需要使用。

十三、 webpack 热更新

上一节介绍监控自动编译,当我们保存文件后,会自动编译文件,但是我们还是需要手动去刷新页面,才能看到编译后的结果。

于是为了自动编译之后,再自动重新加载,我们就可以使用 webpack-dev-server 来启动一个简单 web 服务器,实时重新加载。

1. 开启热更新

插件安装:

  1. npm install webpack-dev-server --save-dev

使用插件:

  1. // webpack.dev.js
  2. const webpack = require('webpack');
  3. const webpack = require('webpack');
  4. let devConfig = {
  5. // ... 省略其他
  6. devServer: {
  7. contentBase: path.join(__dirname, 'dist'),
  8. compress: true,
  9. hot: true,
  10. overlay: true,
  11. open:true,
  12. publicPath: '/',
  13. host: 'localhost',
  14. port: '1200'
  15. }
  16. plugins: [
  17. new webpack.NamedModulesPlugin(), // 更容易查看(patch)的以来
  18. new webpack.HotModuleReplacementPlugin() // 替换插件
  19. ]
  20. }

启动热更新:

  1. npx webpack-dev-server --config webpack.dev.js

常用配置:

  1. contentBase: path.join(__dirname, 'dist'), //本地服务器所加载的页面所在的目录
  2. clinetLogLevel: 'warning', // 可能值有 none, error, warning 或者 info (默认值)
  3. hot:true,//启动热更新替换特性,需要配合 webpack.HotModuleReplacementPlugin 插件
  4. host:'0.0.0.0', // 启动服务器的 host
  5. port:7000, // 端口号
  6. compress:true, // 为所有服务启用gzip压缩
  7. overlay: true, // 在浏览器中显示全屏覆盖
  8. stats: "errors-only" ,// 只显示包中的错误
  9. open:true, // 启用“打开”后,dev服务器将打开浏览器。
  10. proxy: { // 设置代理
  11. "/api": {
  12. target: "http://localhost:3000",
  13. pathRewrite: {"^/api" : ""}
  14. }
  15. }

这时候我们访问 http://localhost:1200/main.html 就可以看到页面,并且修改文件,页面也会同时刷新。

2. 优化命令

我们可以将 npx webpack-dev-server--config webpack.dev.js 写到 package.json 中作为一个命令:

  1. // package.json
  2. "scripts": {
  3. "test": "echo \"Error: no test specified\" && exit 1",
  4. "build": "npx webpack --config webpack.dev.js --watch",
  5. "dist": "npx webpack --config webpack.prod.js",
  6. + "watch": "npx webpack-dev-server --config webpack.dev.js"
  7. },

十四、 webpack 设置代理服务器和 babel 转换及优化

1. 设置代理服务器

接着上一节,接下来给 webpack 设置代理服务器:

  1. // webpack.dev.js
  2. let devConfig = {
  3. // ... 省略其他
  4. devServer: {
  5. // ... 省略其他
  6. proxy: {
  7. "/api": { // 以 '/api' 开头的请求,会跳转到下面的 target 配置
  8. target: "http://192.168.30.33:8080",
  9. pathRewrite: {
  10. "^api": "/mock/api"
  11. }
  12. }
  13. }
  14. }

最后当我们请求 /api/getuser 接口,就会转发到 http://192.168.30.33:8080/mock/api

2. babel 转换及优化

babel-loader 插件的安装,已经提前介绍,在【十一、 webpack 配置合并和提取公共配置】中。

这里讲一下 babel-loader 的优化。

babel-loader 可以配置 cacheDirectory 来提高打包效率:

  • cacheDirectory:默认值 false,开启后构建时会缓存文件夹,后续从缓存中读取,将提高打包效率。

十五、 webpack 开启 Eslint

安装插件:

  1. npm install eslint eslint-loader --save-dev

另外还需要安装 eslint 解释器、校验规则等:

  1. npm install babel-loader standard --save-dev

2. 添加 .eslintrc.js

在项目根目录创建 .eslintrc.js,指定 eslint 规则。

这份配置内容有点多,可以去 我的 gist 复制https://gist.github.com/pingan8787/8b9abe4e04bed85f9d7846e513ed2e11 。

3. 添加 .eslintignore

在项目根目录创建 .eslintignore,指定 eslint 忽略一些文件不校验,比如内容可以是:

  1. /dist/
  2. /node_modules/

十六、 webpack 解析模块拓展名和别名

在 webpack 配置中,我们使用 resolve 来配置模块解析方式。

这是非常重要的,比如 import_from'lodash' ,其实是加载解析了 lodash.js 文件。

该配置就是用来设置加载和解析的方式。

在解析过程中,我们可以进行配置:

1. resolve.alias

当我们引入一些文件时,需要写很长的路径,这样使得代码更加复杂。

为此我们可以使用 resolve.alias,创建 import 或 require 的别名,使模块引入更加简单。

使用配置:

  1. // webpack.common.js
  2. module.exports = {
  3. entry: './src/index.js',
  4. + resolve: {
  5. + alias: {
  6. + '@' : path.resolve(__dirname, 'src/')
  7. + }
  8. + }
  9. // 省略其他
  10. }

alias 参数的含义:

使用 @ 来替代 path.resolve(__dirname,'src/') 这个路径,接下来我们测试看看。

我们在 src/ 目录下新增 leo.js

  1. // leo.js
  2. export let name = 'pingan';

再到 src/index.js 中引入:

  1. // index.js
  2. import { name } from '@/leo.js';

这样就能正常引入。

当然,我们也可以根据实际情况,为不同路径设置不同别名

  1. // webpack.common.js
  2. alias: {
  3. '@' : path.resolve(__dirname, 'src/')
  4. + 'assets' : path.resolve(__dirname, 'src/assets/')
  5. }

更多参数介绍,可访问中文官网的介绍:

2. resolve.extensions

resolve.extensions 用来自动解析确定的扩展,让我们在引入模块的时候,可以不用设置拓展名,默认值为:

  1. extensions: [".js", ".json"]

使用配置:

  1. // webpack.common.js
  2. import { name } from '@/leo';

十七、 webpack 配置外部拓展

当我们使用 CDN 引入 jquery 时,我们并不想把它也打包到项目中,我们就可以配置 externals 外部拓展的选项,来将这些不需要打包的模块从输出的 bundle 中排除:

  1. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>

配置 externals

  1. // webpack.common.js
  2. module.exports = {
  3. // ... 省略其他
  4. + externals: {
  5. + jquery: 'jQuery'
  6. + },
  7. }

通过上面配置,我们就不会把不需要打包的模块打包进来。并且下面代码正常运行:

  1. import $ from 'jquery';
  2. $('.leo').show();

更多参数介绍,可访问中文官网的介绍:

十八、 webpack 打包分析报表及优化总结

1. 生成报表

这里我们使用 webpack-bundle-analyzer 插件,来对打包后的文件进行数据分析,从来找到项目优化的方向。

webpack-bundle-analyzer 使用交互式可缩放树形图可视化 webpack 输出文件的大小。

安装插件:

  1. npm install webpack-bundle-analyzer --save-dev

这个我们只有在开发环境中使用。

使用插件:

  1. // webpack.dev.js
  2. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  3. module.exports = {
  4. plugins: [
  5. new BundleAnalyzerPlugin()
  6. // ...
  7. ]
  8. }

配置完成以后,我们执行 npm run build 打包,打包完成后,会自动打开一个数据报表分析的页面,地址是 http://127.0.0.1:8888/

webpack-bundle-analyzer 将帮助我们:

  • 看清楚我们包内都包含什么模块;

  • 准确看出每个模块的组成;

  • 最后优化它!

我们经常将报表中区域最大的模块进行优化!

2. 通过报表优化项目

我们可以看出,打包后的项目中 lodash.js 占了非常大的内存,我们就针对 lodash.js 进行优化。

我们将 lodash.js 改为 CDN 引入:

  1. // index.html
  2. <script src="https://cdn.bootcss.com/lodash.js/4.17.15/lodash.js"></script>

然后去设置上一节讲到的 externals

  1. // webpack.common.js
  2. externals: {
  3. jquery: 'jQuery',
  4. + lodash: '_'
  5. },

再打包以后,可以看到 lodash.js 已经不在包里面了:

并且打包后的文件,也能正常运行:

更多参数介绍,可访问中文官网的介绍:

参考资料

  • 《Webpack4 中文网》

  • 《2019最新Webpack4.0教程4.x 成仙之路》


《Webpack4入门手册(下)(共 18 章)》到这里结束。


总结

本文是根据 《2019最新Webpack4.0教程4.x 成仙之路》 学习总结下来的学习之路,适合入门,涉及范围较多,内容比较长,需要能静下心来学习。

内容如果有误,欢迎留言指点,我会及时修改。

本文代码最终托管在我的 github 上,点击查看(https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Webpack/introduction/README.md)。

希望自己的文章会对各位有所帮助,也欢迎各位大佬指点。

原创系列推荐

1.JavaScript 重温系列(22篇全)

2.ECMAScript 重温系列(10篇全)

3.JavaScript设计模式 重温系列(9篇全)

4.正则 / 框架 / 算法等 重温系列(16篇全)

5.【汇总】59篇原创系列汇总

你点的每个赞,我都认真当成了喜欢

【Webpack】320- Webpack4 入门手册(共 18 章)(下)的更多相关文章

  1. 【Webpack】319- Webpack4 入门手册(共 18 章)(上)

    介绍 1. 背景 最近和部门老大,一起在研究团队[EFT - 前端新手村]的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平. 本文也是属于[E ...

  2. 从新手到高手c++全方位学习 pdf + 视频教程 共18章

    淘宝已经和谐了这个网站,原网址:https://item.taobao.com/item.htm?spm=a1z09.8149145.0.0.mb00D0&id=17350311256& ...

  3. 【Cute-Webpack】Webpack4 入门手册(共 18 章)

    介绍 1. 背景 最近和部门老大,一起在研究团队[EFT - 前端新手村]的建设,目的在于:帮助新人快速了解和融入公司团队,帮助零基础新人学习和入门前端开发并且达到公司业务开发水平. 本文也是属于[E ...

  4. 《Python学习手册 第五版》 -第18章 参数

    在函数的定义和调用中,参数是使用最多喝最频繁的,本章内容就是围绕函数的参数进行讲解 本章重点内容如下: 1.参数的传递 1)不可变得参数传递 2)可变得参数传递 2.参数的匹配模式 1)位置次序:从左 ...

  5. DPDK2.1 linux上开发入门手册

    1引言 本文档主要包含INTEL DPDK安装和配置说明.目的是让用户快速的开发和运行程序.文档描述了如何在不深入细节的情况下在linux应用开发环境上编译和运行一个DPDK应用程序. 1.1文档总览 ...

  6. webpack4入门配置

    下面是抄过来的,方便自己翻越 webpack4.x入门配置   1.首先npm install webpack webpack-cli webpack-dev-server -g (mac电脑用超级管 ...

  7. webpack4入门到进阶案例实战课程

    愿景:"让编程不在难学,让技术与生活更加有趣" 更多教程请访问xdclass.net 第一章 webpack4前言 第一集 webpack4入门到进阶案例实战课程介绍 简介:讲述w ...

  8. react webpack.config.js 入门学习

    在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...

  9. webpack4入门

    前提 已安装node(版本号>4.0,已自带NPM) mac机器 有一个空目录 无webpack.config.js配置打包 快速构建package.json文件. npm init -y 安装 ...

随机推荐

  1. pat 1065 A+B and C (64bit)(20 分)(大数, Java)

    1065 A+B and C (64bit)(20 分) Given three integers A, B and C in [−2​63​​,2​63​​], you are supposed t ...

  2. lqb 入门训练 A+B问题

    入门训练 A+B问题 时间限制:1.0s   内存限制:256.0MB     问题描述 输入A.B,输出A+B. 说明:在“问题描述”这部分,会给出试题的意思,以及所要求的目标. 输入格式 输入的第 ...

  3. HTML5之worker开启JS多线程模式及window.postMessage跨域

    worker概述 worker基本使用 window下的postMessage worker多线程的应用 一.worker概述 web worker实际上是开启js异步执行的一种方式.在html5之前 ...

  4. 【Java】抽象类和接口详解

    抽象类 一.抽象类的概述 现在请思考一个问题:假如我现在又Dog.Cat.Pig等实例对象,现在我们把它们都抽象成一个Animal类,这个类应该包含了这些Dog.Cat.Pig等实例对象eat的功能, ...

  5. Unittest框架的从零到壹(一)

    前言 Python中有非常多的单元测试框架,如unittest.pytest.nose.doctest等,Python2.1及其以后的版本已经将unittest作为一个标准模块放入Python开发包中 ...

  6. Nginx 代理本地文件夹(Windows环境)

    安装环境: win10 nginx-1.17.2 步骤: 一.打开nginx.conf 路径:\nginx-1.17.2\conf\nginx.conf 二.编辑 配置跨域以及代理文件夹路径 三.启动 ...

  7. windows系统与SQL SERVER 2008数据库服务性能监控分析简要

    软件系统性能测试体系流程介绍之windows系统与SQL SERVER 2008数据库服务性能监控分析简要 目前大部分测试人员对操作系统资源.中间件.数据库等性能监控分析都是各自分析各自的监控指标方式 ...

  8. Chapter 03—Getting Started with graphs

    例01:一个简单的例子               一. 图形参数 1. 符号和线条 例02: plot(dose,drugA,type="b",lty=3,lwd=3,pch=1 ...

  9. 相对和绝对路径、cd命令、创建和删除目录、rm命令 使用介绍

    第2周第1次课(3月26日) 课程内容:2.6 相对和绝对路径2.7 cd命令2.8 创建和删除目录mkdir/rmdir2.9 rm命令 2.6相对和绝对路径 任何一个文件都有一个从根开始的路径,绝 ...

  10. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...