目录 § ⇧
- 1. 前置知识 §
- 2. 用到的工具 §
- 3.
webpack功能 § - 4.
CRM学webpack§ - 5. 从webpack看前端工具的历史 §
- 6. 总结 §
- 4.10. 目标十:自己写一个
loader§ - 4.11. 目标十一:自己写一个
plugin§ - 7. 问答 §
- 8. 学英语 §
0.安装webpack
- webpack 的运行,是需要依赖 node.js 的运行环境
- 官网https://webpack.js.org/
- Get Started
- 查看目前有哪几种版本 对应版本号
npm info webpack versions - 全局安装
npm i -g webpack@4 webpack-cli@3 - 项目文件安装
npm init -y && npm install webpack@4 webpack-cli@3 --save-dev - 或者
yarn init -y && yarn add webpack@4 webpack-cli@3 webpack-dev-server@3 --dev - 或者
npm init -y && yarn add webpack@4 webpack-cli@3 webpack-dev-server@3 --dev - 不可两者都用
webpack@4.44.1webpack-cli@3.3.12webpack-dev-server@3.11.0
前端工程化的理解
- 模块化的价值 sea.js前端模块化开发的价值 #547
- 解决命名冲突
- 依赖统一管理
- 提高开发时代码可读性
- 代码解耦,提高复用性
webpack 模块能以各种方式表达它们的依赖关系
ES2015import语句CommonJSrequire()语句AMDdefine和require语句css/sass/less文件中的@import语句。stylesheeturl(...)或者HTML<img src=...>文件中的图片链接- …
1. 前置知识 §
ES6
- let / const / 箭头函数 / … / class / Promise
- 继承 / this / 原型
CSS 语和布局
- flex
MVC 概念
- Model / View / Controller /EventHub
工具的使用
- VSCode / WebStorm
- 终端命令行 npm / yarn / http-server / parcel / git
2. 用到的工具 §
webpack@4安装方法见官网Getting Started
- 在
webpack后面加个@4即可 - 如果
webpack升级到了5, 思路依然有效
webpack-dev-server
- 用于本地预览
- parcel 不和 webpack 配套
Yarn
- 用于build发布
正式进入框架阶段
3. webpack功能与使用 §
一个包含前端的项目,里面可能有多个 .js, 多个 .css , 多个静态图片, 多个其他前端资源。 一些 js 资源彼此之前存在依赖关系,当一个页面需要加载多个 .js 的话,也会拖累整个页面的加载速度
为了解决这个问题,webpack 就把各种各样的静态资源,打包成了一个所谓的 assets. 加快浏览器加载
- 转译代码(ES6转为ES5,SCSS转为CSS)
- 构建build
- 代码打包
- 代码压缩
- 代码分析
Vue React Webpack 知识对基础知识的杂糅
使用webpack运行
|
|
调用本地局部安装的 webpack
|
|
自动寻找本地文件夹的 webpack
|
|
npx不能识别路径中的空格
4. CRM学webpack §
- 目标一:用
webpack转译JS - 目标二:理解文件名中
hash的用途 - 目标三:用
webpack生成HTML - 目标四:用
webpack引入CSS - 目标五:用
webpack引入SCSS - 目标六:用
webpack引入LESS和Stylus - 目标七:部署到
GitHub Pages - 目标八:用
webpack的file-loader引入图片引入图片 - 目标九:用
webpack的import()实现懒加载 - 目标十:自己写一个
loader - 目标十一:自己写一个
plugin - 目标十二:用
webpack实现模块热替换HMR - 目标十三:用
webpack引入TypeScript - 目标十四:用
Flow检查器 - 目标十五:用
webpack引入各大框架VuwReactElectron
4.1. 目标一:用webpack转译JS §
途径
- 进入官网Getting Started
- Copy
- Run
- Modify
什么是转译
JS
- 分析JS代码,并转译成低版本浏览器可以用的JS
./src/x.jsexport default 'xxx'./src/index.jsimport x from './x.js'; console.log(x)- 项目路径中
npx webpack,查看dist目录中main.js
初始化 webpack.config.js
去除
npx webpack的警告:WARNING in configuration The 'mode' option has not been set...
- 官网webpack->Configuration
- 在 Configuration 去除WARNING 设置模式(mode) 生产模式(production) 开发模式(development):
webpack.config.js
|
|
- 再运行
npx webpack
生产模式(production) 开发模式(development)区别
- 在
dist/main.js中,生产模式压缩的代码体积小;开发模式,便于Debug - 如果暂时没有影响就不用管
- 之后详细说明如何切换两者
webpack 配置 entry 和 output
修改
webpack.config.js> module.exports> entry默认入口文件entry: './src/index.js'
|
|
- 再运行
npx webpack - 查看
dist路径后多了foo.bundle.js - 修改
output> filename为main.js - 手动删除原来的dist路径
- 再运行
npx webpack - 配置
entry和output,会把./src/路径下的JS文件转译后放到dist路径下 - 默认目标路径可以不写
path: path.resolve(__dirname, 'dist') - 入口和出口的配置
4.2 目标二:理解文件名中hash的用途 §
- 官网webpack->Caching
- 出口的文件名改为
'[name].[contenthash].js' - 再运行
npx webpack得到main.xxx.js文件名后多了hash值用来HTTP缓存
HTTP响应头中的Cache-Control
- 设置缓存头
- 点开响应头
Response Headers中的Cache-Control public, max-age=31536000设置最大缓存一年- 缓存过期后,再重新请求
HTTP缓存的意义
- 缓存一年
- 除了
index.html外的资源存储在用户浏览器的缓存中 - 减少连接数,访问时间不用重复下载资源
- 资源的下载速度之间可差百倍
怎么更新
JS CSS之类的资源
- 对资源文件内容做一个MD5 文件名后加hash
'[name].[contenthash].js'就是做这个的- 每次修改文件内容,再次打包,得新到的
main.xxx.js - 文件内容和文件名有一一对应的关系
- 之前的缓存就没用了
- 浏览器就会更新资源 ,删除原来的缓存
为什么不缓存
index.html
- 需要在首页中存储更改hash的文件名
- 通知浏览器其他资源的入口
- 首页一定不能做缓存,或者设置的最大缓存时间不能太长
- 链接到 【HTTP非全解】
dist文件越来越多,在
yarn build时设置自动删除并构建
- 在
package.json> script中设置rm -rf dist && npx webpack - 可省略
npx,自动寻找webpack,rm -rf dist && webpack
package.json
|
|
yarn build或者npm run build
webpack.config.js
|
|
4.3 目标三:用webpack生成HTML §
之前先用git提交下代码备份
- 搜索
webpack create html page - 官网webpack->HtmlWebpackPlugin
- github jantimon/html-webpack-plugin
安装
HtmlWebpackPlugin
|
|
配置
webpack.config.js
|
|
- 运行
yarn build - 自动生成一个空的html,自动引入了
index.xxx.js - dist目录下的文件都是自动生成的,不可手动修改
生成一个html模板
- 新建
./src/assets目录index.html 配置
webpack.config.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15const HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path'); module.exports = { mode: 'development', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'index.[contenthash].js' }, plugins: [new HtmlWebpackPlugin({ title: 'webpack', // filename: 'test.html', template: 'src/assets/index.html' })] };修改
index.html为常用初始模板,之后配置对应的标签模板
<title><%= htmlWebpackPlugin.options.title %></title>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16<!DOCTYPE html> <html lang="zh-Hans"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,viewport-fit=cover"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <div></div> </body> </html>
x.js
|
|
index.js
|
|
可以实现
- 自动更新html文件名
- 自动使用配置里的title标签
- 自动把引入的js标签放到body底部
要点
- 自动更改文件名
- 插件
HtmlWebpackPlugin生成HTML
4.4 目标四:用webpack引入CSS §
webpack 引入模块化 CSS
x.css
|
|
x.js
|
|
index.js
|
|
- 编译css时报错
ERROR in ./src/x.css 1:5.Module parse failed: Unexpected token (1:5)You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file...
需要
css-loader
css-loader
- 搜索
webpack css-loader - 官网webpack->css-loader
- 安装
yarn add css-loader --dev
配置
webpack.config.js
|
|
按报错安装所需的工具模块
Module not found: Error: Can't resolve 'style-loader'
- 安装
style-loader -
1yarn add style-loader --dev 再运行
yarn buildstyle-loader把css-loader解析的CSS代码放到页面的head > style标签中开发模式下使用,无需用
link标签引入CSS文件没有
Cache-Control做缓存,未部署
x.js观察引入的x.css,之前暂时删掉webpack.config.js的'style-loader',
|
|
cd ..回到上级目录,再运行yarn buildcd dist后,使用hs -c-1查看控制台
使用更方便的
webpack-dev-server自动刷新部署代替hs -c-1
- 搜索
webpack webpack-dev-server - 官网webpack -> 开发中 Server(devServer) webpack-dev-server
- 官网webpack -> DevServer en
- 官网webpack -> DevServer zh
- 官网webpack -> DevServer 开发环境 zh
- 先将
mode设置为'development' - 使用 source map,配置
devtool: 'inline-source-map',追踪error(错误) 和 warning(警告) 在源代码中的原始位置 -
1yarn add webpack-dev-server --dev
配置
webpack.config.js
|
|
package.json
--open表示是否打开浏览器,可删除1 2 3 4 5 6 7 8... "scripts": { "build": "rm -rf dist && webpack", "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open", "watch": "webpack --watch" }, ...运行
yarn start或者运行
npm run start访问端口
http://localhost:8080/测试实时更新页面
background: gray;不需要在开发时频繁
yarn build或是手动删除dist不会创建或依赖
dist目录,在内存中运行,自动更新
singletonStyleTag
使用单个的
<style>标签加载所有css属性,或者是每个css模块一个<style>标签
- webpack style-loader singletonStyleTag
- 默认值是
false(每个css模块一个<style>标签) - 默认情况下,每一个css文件会变为一个
<style>标签 - 实际加载中,可能有多个
<style>标签; - 默认值为
false(而不是原文中说的默认情况下启用此选项) - 当该值设置为
true时,那么,原本多个<style>标签会被合并成一个<style>标签 - 官方文档上写的是默认开启,实际上是不开启的
除了用
style-loader生成style,也可以吧CSS抽成文件
使用MiniCssExtractPlugin(生产环境下)
- 使用插件提取
CSS文件 - 搜索
webpack css 抽成文件webpack css extract plugin - webpack MiniCssExtractPlugin
安装插件
1yarn add mini-css-extract-plugin --dev
配置
webpack.config.js
|
|
目前实现了
MiniCssExtractPlugin把css-loader解析的CSS代码放到页面的head > link标签中- 实时生成带
hash的js文件到script标签中,并放在body标签内的最后 - 做
Cache-Control适用于生产环境
要点:引入
css的两种方式
- 开发时可以使用
JS生成style,快速,不需要在dist中生成css文件 - 发布时可以把
CSS抽成带hash文件,可以做缓存
如何做到在开发时用第一种方式
发布时,即在生产环境中,用第二种方式
- 根据模式选择不同的途径
- 生产环境:
yarn build;- 对应的
package.json中:"build": "rm -rf dist && webpack" - 做缓存,用
MiniCssExtractPlugin生成link标签 - 引入带
hash的CSS文件 - 插入
head标签
- 对应的
- 开发环境:
yarn start;- 对应的
package.json中:"start": "webpack-dev-server" - 不做缓存,用
css-loader生成style标签 - 插入
head标签
- 对应的
终端命令行使用帮助文档
webpack --help
- 未全局安装的话用
npx webpack --help - 设置配置文件
package.json的路径 "build": "rm -rf dist && webpack --config webpack.config.prod.js"- 意思是,在
build时,不适用默认的配置,而是使用webpack.config.prod.js的配置
package.json
|
|
yarn start- 查看
dist,目录中index.html是否引入了style标签
使用两个 webpack config 文件,切换开发模式
默认
webpack.config.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26const HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path'); module.exports = { mode: 'development', entry: './src/index.js', devtool: 'inline-source-map', devServer: { contentBase: './dist', }, output: {...}, plugins: [ new HtmlWebpackPlugin({...}), ], module: { rules: [ { test: /\.css$/, // mode: 'development' // `yarn start` // css-loader use: [ 'style-loader', 'css-loader' ] } ] } };创建生产环境的
webpack.config.prod.js1 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 40let HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const path = require('path'); module.exports = { mode: 'production', entry: './src/index.js', devtool: 'inline-source-map', devServer: { contentBase: './dist', }, output: {...}, plugins: [ new HtmlWebpackPlugin({...}), new MiniCssExtractPlugin({ filename: '[name].[contenthash].css', chunkFilename: '[id].[contenthash].css', ignoreOrder: false, }), ], module: { rules: [ { test: /\.css$/, // mode: 'production' // `yarn build` // MiniCssExtractPlugin use: [ { loader: MiniCssExtractPlugin.loader, options: { publicPath: '../', }, }, 'css-loader' ] } ] } };
继承共有属性
webpack.config.base.js
配置继承
webpack.config.base.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16let HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path'); module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'index.[contenthash].js' }, plugins: [ new HtmlWebpackPlugin({ title: 'webpack', template: 'src/assets/index.html' }) ] };
webpack.config.js
|
|
webpack.config.prod.js
|
|
yarn buildproduction modeyarn startdevelopment mode
用工具插件webpack-merge实现自动切换
配置分离 生产环境构建
- 为每个环境编写彼此独立的 webpack 配置
- 生产环境 webpack v5.0 beta
- 使用webpack-merge区分生成环境和开发环境
- webpack-merge使用说明
- 浅析webpack-merge源码
- 霖呆呆的webpack之路-构建方式篇
- 带你深度解锁Webpack系列(进阶篇)
- webpack常用插件汇总
环境变量
- 使用环境变量
- webpack4多环境变量问题
- Webpack配置环境切换
- Webpack下多环境配置的思路
- Webpack配置环境切换
- webpack开发与生产环境配置
- 通过Webpack全局配置开发环境和多种生产环境的请求地址
- Webpack + ES6 最新环境搭建与配置
- 为什么我们要做三份 Webpack 配置文件
- webpack实现开发、测试、生产等环境的打包切换
- 配置webpack中dev.env.js、prod.env.js,解决不同命令下项目启动和打包到指定的环境
- 浅谈Webpack下多环境配置的思路
- Webpack:环境变量的使用方法
- webpack开发环境和生产环境切换原理
- webpack开发和生产环境的建立
webpack实现了
- 内置
babel-loader转译n个JS文件为1个JS文件 - 用
JSimport CSS,style/css-loader就转译为style标签 - 用
MiniCssExtractPlugin转译n个CSS文件为1个CSS文件
loader vs plugin
loader和plugin的区别是
- 翻译一下,
loader是加载器,plugin是插件 loader作用加载文件plugin作用扩展/加强功能
举例
babel-loader用来加载JS,转移为低版本的JSstyle-loader和css-loader用来加载CSS,变为页面中的标签- new 一个
HtmlWebpackPluginMiniCssExtractPlugin - plugins 需要安装后require() loader直接安装依赖使用
搜英文关键词,选择性地CRM
4.5 目标五:用webpack引入SCSS §
将
x.css改名为x.scss,在x.js里改为import css from './x.scss'
注意不要覆盖配置中的
module
- 在
rules: []里加一句...base.module.rules,
webpack.config.base.js
|
|
webpack.config.js
|
|
webpack.config.prod.js
|
|
x.js
|
|
要点
- webpack sass-loader
node-sass已经过时代替使用
dart-sass1yarn add sass-loader sass dart-sass --dev
4.6. 目标六:用webpack引入PostCSS、 LESS 和 Stylus §
要点
SCSS、LESS和Stylus使用原理完全没区别- 改个后缀,兼容CSS语法的部分通用
Stylus兼容SASS和LESSPostCSS- webpack less-loader v4.44.0
- webpack less-loader v5.0 beta
- webpack less-loader v5.0 beta zh
- webpack stylus
-
1 2 3 4 5yarn add less-loader --dev && yarn add stylus-loader stylus --dev && yarn add postcss-loader --dev && yarn add autoprefixer --dev && yarn add postcss-cssnext --dev
x.js
|
|
index.js
|
|
webpack.config.base.js
|
|
webpack.config.js
|
|
webpack.config.prod.js
|
|
4.7. 目标七:用webpack引入图片 §
index.js
|
|
报错
Cannot set property 'innerHTML of null'
.innerHTNL前面的div是个null- 未取到
div,console.log(div) - 注意
<div id="app"></div>中的id没有#
src/assets/index.html
|
|
yarn start的页面中为请求到图片
- 因为
webpack-dev-server加载的路径并不是当前目录,而是dist目录
怎样加载图片路径
index.js
|
|
import的时什么将由loader决定- 搜
webpack image-loader,由许多可供使用的 - 使用
file-loader引入本地图片 - 处理顺序是从数组的走后一项开始的
image-webpack-loader插件放在处理顺序的最后,先用其他(url-loader)引入加载网络图片- webpack Asset Management
- webpack file-loader
- github file-loader
Error: Can't resolve 'file-loader'
- 手动安装
file-loader yarn add file-loader --dev
webpack.config.base.js
|
|
index.js
|
|
- 自动添加哈希
- 图片放到本地的
assets - 使用
import得到路径的引用 - 将引用放到
src file-loader的作用就是把文件变成文件路径
4.8. 目标八:用webpack的 import() 实现懒加载 资源异步加载 §
当模块数量过多、资源体积过大时,将暂时用不到的模块延迟加载
使得页面初次渲染时用户下载的资源尽可能小
后续的模块等到恰当的时机再去触发加载
- 提升用户体验
- 按需分步加载
import函数异步加载。返回promise对象实例- 不推荐使用
require.ensure - import MDN
- 动态import
- export MDN
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15const button = document.createElement('button') button.innerText = '懒加载' button.onclick = () => { console.log("点击了 button") const lazyPromise = import('./lazy.js') // 加载时异步的 拿到的是一个 Promise对象实例 lazyPromise.then((module) => { console.log(module) const fn = module.default fn() }, () => { console.log("模块加载错误") }) } div.appendChild(button)
4.9. 目标九:部署到GitHub Pages §
本地打包
|
|
本地预览
|
|
上传代码
webpack 一键部署到 github
原来的部署过程
1.将“站点”部署 上传 dist 目录
- githubPages
2.使用git分支 上传到 gh-pages 分支
|
|
手滑把
.gitignore删除了,重置,撤回上一步1git reset --hard HEAD
只保留
distnode_modules.gitignore
|
|
拷出 dist 的所有内容
|
|
上传网站根目录
|
|
一个分支用来写代码 一个分支用来预览
- loading 顺时针转 请求 逆时针转 下载
- git stash 将修改过的文件暂存
- git checkout master
- git stash pop
用脚本一键部署
deploy.sh
回到上一个分支
git checkout -1 2 3 4 5 6 7 8 9yarn build && git checkout gh-pages && rm -rf src *.sh *.js *.json yarn.lock *.css *.scss *.less *.styl *.gif *.png && mv dist/* ./ && rm -rf dist; git add . && git commit -m "preview gh-pages" && git push git checkout -
以后如果改了代码 需要更新预览,先提交master 在一键脚本
|
|
webpack 一键部署到 gitee
- 登录网站 新建仓库
- 点击SSH
- 在
git remote add origin git@gitee.com:xmasuhai/webpack-demo-1.git中修改origin为gitee git remote add gitee git@gitee.com:xmasuhai/webpack-demo-1.gitgit push -u gitee mastergit remote -v查看仓库
再次新建一个脚本
deploy_cn.sh
|
|
git github gitee gitlab
4.10. 目标十:自己写一个loader §
4.11. 目标十一:自己写一个plugin §
4.12. 目标十二:用webpack实现模块热替换HMR §
- 目标十二:用
webpack实现模块热替换HMR - 目标十三:用
webpack引入TypeScript - 目标十四:使用
Flow检查器 - 目标十五:用
webpack引入各大框架VuwReactElectron - 目标十六:用
webpack实现i118n
5. 从webpack看前端工具的历史 §
- 链接到 理性看待node
9. 死掉的前端工具 §
- Grunt 太慢,几死
- Gulp 速度ok 但没 webpack 繁荣
- Require.js 几死
- Sea.js 已死
- Browserify 已死
9. 和webpack竞争的工具 §
rollup
- 比 webpack 的打包体积更小
- 生态不丰富
- 适合库的开发
parcel
- 比 webpack 配置简单
- 公司要求负载的配置,变态的需求
- 适合demo学习
snowpack
9. 基于webpack的工具 §
@vue/cli
- 快速创建
vue项目 - 基本不用配置
- 特殊配置看文档
create-react-app
- 快速创建
react项目 - 基本不用配置
- 特殊配置看文档
@angular/cli
- 快速创建
angular项目 - 基本不用配置
- 特殊配置看文档
6. 总结 §
术语总结 自我驱动学习法
- 定一个小目标
- 尽一切实现
- 再定一个
要点
- 不要定太难完成的目标
- 不要等别人给你定目标
7. 问答 §
问答1:要将
webpack学到什么程度
- 给一个需求就能搞定的程度
- CRM现有解决方案
问答2:面试问
webpack怎么答
- 相关博客
- 几个手写
webpack config的项目 - 使用
@vue/cli、create-react-app
8. 学英语 §
- 调手机操作系统语言为英语
- 订阅
Hacker News、JS Daily - 优先看英文文档
工具
- 词典
- 抽离
extract
参考文章
- Webpack.pdf
- 代码
- FrankFang/webpack-demos
- FrankFang/webpack-demos-1
- FrankFang/webpack-demos-2
- FrankFang/webpack-demos-3
- webpack务虚扫盲
- 本科毕业设计的前端技术总结(三):这可能是最详尽的Webpack基础总结
- webpack多页面打包实践
相关文章
- 无