特别注意:webpack 4.0 和 3.0 差别很大,该文档主要是 关于 webpack 4.0
前言
1、背景
网页中会引用的常见的静态资源?
js、
css、.css .sass .scss .less
images、
字体文件、
模板文件
网页中引入静态资源多了有什么问题?
1.网页加载速度慢,因为我们发起了很多次的二次请求
2.要处理错综复杂的依赖关系
如果解决上述两个问题?
1.样式和js :合并、压缩
2.图片:尺寸小的图片base64编码
3.使用requireJs 也可以使用webpack 解决各个包之间的复杂依赖关系
2、webpack是什么
是什么?
前端资源的 加载/打包 工具, 将多种静态资源(css,js,less等) 转换 成一个静态文件(static,assets),减少了页面的请求,也是项目构建工具,通过该工具,可以实现对项目的 加载打包
可以做的事情:
代码转换、(转换成浏览器能识别的形式) 文件优化、(压缩代码体积,合并文件) 代码分割、代码合并、自动刷新、代码校验、自动发布
技能基础
node基础,会npm使用
es6语法
学习目标
webpack常用配置
掌握webpack流程
基本使用
1.安装
在node.js 环境下,创建一个新目录,初始化npm,然后开始安装
npm init -y
在本地安装 webpack , webpack-cli
npm install webpack webpack-cli --save-dev
2.创建文件基本结构
/src “源”代码是用于书写和编辑的代码。
/dist “分发”代码是构建过程产生的代码最小化和优化后的“输出”目录,最终将在浏览器中加载
- dist 压缩后要发布的文件
- src 手写的 源代码 和 资源库
- css 项目用到的手写css文件库
- images 项目用到的图片库
- js 项目用到的js库
- index.html 项目入口文件
- main.js 项目 js 入口文件
- webpack.config.js 打包配置文件
3.开始写项目
3.1原则:
1、手写文件全部在 src 文件夹中
2、逻辑都写入 main,js 中 、所有其他需要用到的资源 都引入 main.js 中
3、结构写在 index.html 中
4.手写好的代码,一定要 打包编译后 才可以使用,才能被浏览器识别
3.2打包编译
作用: 将手写的 src 中的 文件和代码,通过打包编译,进行压缩优化,同时编译成 浏览器能理解的语法
打包命令:
npx webpack
如果有配置文件,根据配置文件打包,如果没有配置文件,默认找到 src/index 打包到 dist/main.js
打包指定目录下的指定文件,并以指定的目录和指定的文件名输出
npx webpack ./src/index.js -o ./dist/bundle.js --mode development
根据某个配置文件打包:
npx webpack --config webpack.config.js
开发模式下打包(未压缩)
npx webpack --mode development
生产模式下打包(压缩的)
npx webpack --mode production
以上的打包命令,可以通过在 package.json 添加一个 npm 脚本(npm script):作为运用打包的快捷方式
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack --mode production",
"dev": "webpack --mode development"
},
每次 手写的代码 修改后,都需要执行 一次 打包命令,将之前打包生成的 bundle.js 替换掉,浏览器效果才会发生变化。
打包流程: 当我们在控制台,直接输入 webpack 命令执行的时候,webpack做了以下几步: 1.首先,webpack发现,我们并没有通过命令的形式,给他指定入口和出口 2.webpack就会去 项目 的根目录中,查找一个叫做 ‘webpack.config.js’ 的配置文件 3.当找到配置文件后,webpack会去解析这个 配置文件,当解析执行完配置文件后,就得到了配置文件中,导出的配置对象 4.当 webpack 拿到配置对象后,就拿到了 配置对象中,指定的 入口 和 出口,然后进行打包构建
3.3插件
想要webpack实现一些本身不具备的功能,需要借助插件来完成
1.下载 install npm install --save-dev 插件名
- 导入插件并且修改配置
webpack.config.js ①require ②plugins数组中,添加实例
3.使用 npm run build
常用插件:
- 清理dist中无用的文件
在每次构建前清理 /dist 文件夹,是比较推荐的做法,因此只会生成用到的文件。 clean-webpack-plugin 是一个比较普及的管理插件。
npm install --save-dev clean-webpack-plugin
+ const { CleanWebpackPlugin } = require("clean-webpack-plugin");
plugins: [
+ new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
npm run build 后,dist中没有垃圾文件
- 自动打包编译的功能
webpack-dev-server 每次更新代码后,使代码可以自动打包编译
npm install --save-dev webpack-dev-server
webpack.config.js
devServer: {
+ contentBase: './dist'
+ },
以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的文件,作为可访问文件。 www.webpackjs.com/configurati…
添加一个 script 脚本,可以直接运行开发服务器(dev server):
"start": "webpack-dev-server --open",
-- hot 热更新(不重新打包为新的版本,只替代更新的部分),页面不刷新的情况下,就可以应用新代码 --port 3000 修改端口号
1.3 使用 在命令行中运行 npm start,就会看到浏览器自动加载页面。
如果现在修改和保存任意源文件,web 服务器就会自动重新加载编译后的代码。
webpack-dev-server帮我们打包生成的bundle.js文件,并没有存到 实际的 物理磁盘上(/dist,一个文件夹就是一个物理磁盘);而是,直接托管到了 电脑的内存 中,所以,我们在 项目根目录中,根本找不到 这个打包好的 bundle.js;我们可以认为,webpack-dev-server 把打包好的 文件,以一种虚拟的形式,托管到了 我们项目的 根目录中,虽然我们看不到它,但是,可以认为,和dist src node_modules 平级,有一个看不见的文件,叫做bundle.js, 这样做的原因是 提交速度快 , 如何在文件中引用这个生成的bundle.js 呢?利用下面的插件即可
webpack 模块打包器,只是打包的功能。所以每次修改了代码,都需要手动重新打包 webpack-dev-serve 一个服务器插件,相当于webpack+apache,启动一个web服务并实时更新修改
- html-webpack-plugin
该插件有两个作用:
1.自动在 内存 中,根据指定页面生成 一个内存 index.html 的页面(不在dist中,看不到) 2.打包后,相关引用关系(img等)和文件路径(打包后的bundle.js)都会按照正确的配置被添加进去
cnpm install --save-dev html-webpack-plugin
const path = require('path');
// 导入这个插件
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
+ plugins: [
+ new HtmlWebpackPlugin({
//指定模板页面,将来会根据 指定的 页面路径,去生成内存中的 页面
+ templat:path.join(_dirname,'./src/index.html'),
//指定 生成页面的 名称
filename:'index.html'
+ })
+ ]
};
配置好,打包编译,即可自动打开这个 在内存中的index.html 页面。
3.4 loader
webpack 本身只能打包 javascript文件,其他资源,如css、字体、图片等,是没办法加载的。这就需要对应的loader 将资源转化,再引入加载。
1.下载相应的loader npm install --save 包名
2.配置好 webpack.config.js配置
3.引入资源包(css文件、字体文件、图片文件) 使用 import
webpack处理第三方文件类型的过程:
1.发现这个 要处理的文件不是js文件, 然后就去配置文件中,查找有没有对应的第三方loader规则, 2.如果能找到这个对应的规则,就会调用 对应的 loader处理 这种文件类型; 3.在调用loader 的时候,是从后向前调用的; 4.当最后一个 loader 调用完毕,会把 处理的结果,直接交给 webpack 进行打包合并,最终输出到 bundle.js 中去
- 1.下载相应依赖
npm install --save 包名
npm install --save-dev 包名
dev 是 develop(开发) 的缩写, devDependencies 开发环境的依赖
//编译css
cnpm install --save-dev style-loader css-loader
cnpm install --save-dev less-loader
cnpm install --save-dev sass-loader
//识别url地址(编译字体图标和图片)
cnpm install --save-dev url-loader file-loader
- 2.配置匹配规则
在 module对象上的 rules 属性,这个 rules 的数组中,存放了 所有的第三方文件的匹配 和处理规则
webpack.config.js配置
const path = require('path');
module.exports = {
module:{
rules:[
{ test:/\.css$/, use: ['style-loader','css-loader'] },
{ test:/\.less$/, use: ['style-loader','css-loader', 'less-loader'] },
{ test:/\.scss$/, use: ['style-loader','css-loader', 'sass-loader'] },
{ test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' },
{ test:/\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
]
}
};
- file-loader 是 url-load 依赖的包,所以不需要写在匹配规则里
给loader传参:匹配规则里的loader都可以被传参,传参方式和在url中传参一样,不过参数是固定写法
{ test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7631 & name=[name].[ext]' },
关于url-loader的 limit 值: limit 给定的值,是图片的大小,单位是byte, 如果我们引用的图片,大于或者等于 给定的limit值,则不会被转为base64 格式的字符串,如果 图片小于给定的 limit值,则会被转为base64格式的字符串。 防止图片重名,打包编译后的图片的名字会自动被改为哈希值,如果想让图片名称和后缀名不变,可以设置参数 name=[name].[ext]。如果既不想重名,又想保留原来的值: name=[hash:8]-[name].[ext]
- 3.引入相应文件
关于import
- js文件,因为会向外暴露一个变量,所以引入的时候 需要 一个 变量 来承接,以防冲突
非js文件,没有这个问题,所以直接导入即可 2.如果要通过路径的形式,去引入node_modules中相关的文件,可以直接省略 路径前面的 node_modules 这一层目录,直接写 包的名称,然后后面跟上具体的文件路径
import $ from 'jquery';
import './css/style.css';
import Icon from './icon.png';
import 'bootstrap/dist/css/bootstrap.css'
babel
处理高级es6 语法的loader 在webpack中,默认只能处理一部分 es6 的新语法,一些更高级的 es6语法 或者 es7语法,webpack是处理不了的; 这时候,通过babel,可以帮我们将 高级的语法转换为 低级的语法,当 babel 把 高级语法转换为 低级的语法之后,会把结果交给 webpack 去打包到 bundle.js中
1.在 webpack 中,可以运行如下两套命令,安装两套包,去安装 babel 相关的loader功能; 1.1 第一套包:
cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev
1.2 第二套包:
cnpm i babel-preset-env babel-preset-stage-0 --save-dev
2.打开 webpack 配置文件,在module 节点下的 rules 数组中,添加一个 新的 匹配规则:
{test:/ \.js$ /, use: 'babel-loader', exclude: / node_modules /}
2.2 注意:在 babe 的loader规则的时候,必须 把 node_modules 目录,通过 exclude 选项排除掉,原因有两: 2.2.1 如果 不排除 node_modules, 则babel会把 node_moduless 中所有的第三方 js文件,都打包编译,这样,会非常消耗 cpu,同时,打包速度非常慢 2.2.2 哪怕 babel 把 node_modules 中的js都编译转换完毕了,但是 项目也无法正常运行。
3.在 项目的 根目录中,新建一个 叫做 .babelrc 的 babel 配置文件,这个配置文件,属于 json格式,所以,在写.babelrc 配置的时候,必须符合json语法规范:不能写注释,字符串必须用双引号 3.1 在 .babelrc 写如下的配置: 大家可以把preset 翻译成 【语法】的意思 { “presets”:[“env”,“stage-0”], “plugins”:["transform-runtime" ] }
4.配置文件
默认状态下,webpack 不需要配置文件,默认了入口点:src/index ,并且将结果 dist/main.js 缩小并优化生产。 如果要扩展功能,在根文件夹中创建一个文件 webpack.config.js ,手写相关配置。 主要包含以下几部分内容:
webpack.config.js
const path = require('path');
module.exports = {
// 入口,表示要使用webpack 打包哪个文件
entry: './src/index.js',
// 输出文件的相关配置
output: {
// 指定 输出文件 的名称
filename: 'bundle.js',
// 出口指定打包好的文件,输出到哪个目录中去
path: path.join(__dirname, './dist')
},
plugins: [
+ new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
module:{
rules:[
{ test:/\.css$/, use: ['style-loader','css-loader'] },
{ test:/\.less$/, use: ['style-loader','css-loader', 'less-loader'] },
{ test:/\.scss$/, use: ['style-loader','css-loader', 'sass-loader'] },
{ test:/\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' },
{ test:/\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
]
}
};
选择配置文件打包: npx webpack --config webpack.config
问题解决:
- json文件中不能添加注释
- 学会查看命令行报错信息,一般会报错
- ** 不是内部或外部命令,也不是可运行......
- 如果是全局安装的,查看是否是环境变量的问题
- 如果是本地安装的,查看是否是node_module 文件丢失
- 如果还不行,删除node_module,重新安装
4.如果安装到一半,暂停安装,再次安装后,很快就安完,但是运行时容易出错,就删掉node_modules 重新安装
5.如果某次打包失败,解决方案:删除已经下载好的node_modules包,重新npm install,再重新打包 npm run build 即可
6.peerDependencies WARNING less-loader@^5.0.0 requires a peer of less@^2.3.1 || ^3.0.0 but none was installed 版本不兼容导致的,重新下载 提示的loader
7. Cannot find module '@babel/core' 安装提示 下载所需要的 module