1.webpack 简介
1.webpack 是什么
webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。
在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
那为什么要用这种构建工具进行打包呢?
从上图中我们可以看出,Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求,解决模块依赖和兼容性
webpack 五个核心概念
-
1.Entry[ˈentri]
- 入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图
-
2.Output[ˈaʊtpʊt]
- 输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
-
3.Loader[ˈləʊdə®]
- Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解JavaScript)
-
4.Plugins
- 插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
-
5.Mode [məʊd]
- 模式(Mode)指示 webpack 使用相应模式的配置。development:开发环境。production:正式环境
选项 描述 development 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin production 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin,OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin
2.webpack 初体验
1.我们创建 webpack-first文件夹初始化 package.json
npm init && npm init -y
2.下载并安装 webpack
需要两个:webpack 核心模块、webpack-cli 命令行工具 可全局安装
npm install webpack webpack-cli -g && npm install webpack webpack-cli -D
3.模块打包
- 在其创建约定俗成的两个子目录 src 和 build;其中:src 表示源文件,build 表示生成发布的文件
- 在src目录下创建index.js作为入口文件
//index.js
function add (x,y) {
// body
return x + y
}
console.log(add(1,2));
- 运行指令 webpack会以 ./src/index.js 为入口文件开始打包 打包后 输出到 ./build/main.js。打包完成后build目录下会多出一个main.js文件
未全局安装webpack的 需要在指令前加上npx
webpack ./src/index.js -o ./build--mode=development && npx webpack ./src/index.js -o./build --mode=development
- 使用node运行打包后的main.js文件或者创建idnex.html文件引入打包后的main.js文件
在build目录下打开终端运行main.js文件 会发现终端打印 3
node .\main.js
- !注意 webpack可以打包js/json文件 但css/img等资源需要借助loader编译
4.打包样式资源
- 在src目录下创建index.css文件并且在index.js文件引入
/* index.css*/
body,html{
background-color: pink;
width: 100%;
height: 100%;
}
//index.js
import './index.css'
/* 刚刚的代码... */
直接运行打包命令,终端会提示打包失败并报出错误
-
这个时候就需要使用webpack的配置文件,在项目根目录下创建webpack.config.js文件,并且下载所需的loader
style-loader: 的功能就一个,在 DOM 里插入一个 style 标签,并且将 css 写入这个标签内
css-loader: 的作用是帮我们分析出各个css文件之间的关系,把各个css文件合并成一段css
我这里安装的是css-loader@3.4.2 style-loader@1.1.3版本
npm install --save-dev css-loader@3.4.2 style-loader@1.1.3
webpack.config.js是webpack的配置文件,它的作用:指示webpack 干哪些活(当你运行webpack指令时 会加载里面的配置); 需要注意的是所有构建工具都是基于node.js平台运行的~模块化默认采用commonjs;也就是说你需要一定的node.js基础并能够理解node中模块化和commonjs语法
__dirname:指的是当前文件所在文件夹的绝对路径
//webpack.config.js
const path = require('path')
module.exports = {
//entry 入口起点 指示webpack以哪个文件开始打包
entry:'./src/index.js',
//output输出 打包后输出到哪去
output:{
// 打包后的文件名称
filename:'main.js',
// 打包后的文件在那个文件夹下; resolve 用来拼接绝对路径
path:path.resolve(__dirname,'build')
},
// loader的配置
module:{
rules:[
//详细的loader配置
//不同文件需要配置不同loader处理
{
//test:匹配哪些文件
test:/\.css$/i,
//use:使用哪些loader进行处理
//注意 use数组中loader执行顺序:从右到左,从下到上 以此执行
use: [
//style-loader 的功能就一个,在 DOM 里插入一个 <style> 标签,并且将 css 写入这个标签内
"style-loader",
//css-loader 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
"css-loader"
]
}
]
},
//plugins配置
plugins:[],
// 打包环境
mode:'development', //开发环境
// mode:'production' //正式环境
}
- 运行打包命令
npx webpack && webpack
- 打包完成后在build目录下创建index.html并引入main.js;运行index.html文件可以看到样式已经生效 并且验证了 style-loader 的功能,在DOM里插入一个style标签,并且将css写入这个标签内
5.打包HTML资源
- 首先需要下载用于打包html资源的插件 该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中
npm i html-webpack-plugin@3.2.0 -D
- 在src目录下创建一个index.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack App</title>
</head>
<body>
</body>
</html>
- 在webpack.config.js文件中引入html-webpack-plugin
//刚刚的代码...
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
//刚刚的代码...
//plugins配置
plugins:[
// html-webpack-plugin 默认会创建一个空的html文件
new HtmlWebpackPlugin({
//以src目录下的index.html作为模板
template:'./src/index.html'
})
],
}
- 运行打包命令后npx webpack 这将会生成一个以src目录下的index.html作为模板的 build/index.html 文件并自动引入打包输出的所有资源(js/css)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
6.打包图片资源
- 下载用于打包图片的loader
npm i url-loader@3.0.0 file-loader@5.0.2 html-loader@0.5.5 -D
- src目录下的index.html新增三个div
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>
<img src="./assets/1.png" width="300px" alt="">
- 在src目录下的index.less文件内添加三个背景图片
#box1{
width: 300px;
height: 150px;
background-image: url(./assets/1.png);
background-repeat: no-repeat;
background-size: 100% 100%;
}
#box2{
width: 300px;
height: 150px;
background-image: url(./assets/2.png);
background-repeat: no-repeat;
background-size: 100% 100%;
}
#box3{
width: 300px;
height: 150px;
background-image: url(./assets/3.png);
background-repeat: no-repeat;
background-size: 100% 100%;
}
- 继续在webpack.config.js中添加loader配置
module.exports = {
module:{
rules:[
//刚刚配置的loader...
{
test:/\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
//图片小于8kb就会转换成base64处理
//优点 减少服请求
//缺点 图片体积更大
limit:8 * 1024,
//需要将esModule:false 不然解析时会出现问题[object Module]
// 关闭url-loader的es6模块化 使用commonjs解析
esModule:false,
//给图片重命名
//[hash:10]取图片的hash的前10位
//[ext]文件原来的扩展名
//[name]:处理文件的名称;
//[contentHash]:在file-loader中和[hash]结果是一致的(在webpack的一些其他地方不一样,后面会讲到);
//[hash:<length>]:截图hash的长度,默认32个字符太长了;
//[path]:文件相对于webpack配置文件的路径;
name:'[hash:10].[ext]'
}
},
{
test:/\.html$/,
//处理HTML中的img图片(负责引入img,从而能被url-loader进行处理)
loader:'html-loader'
},
// 打包其他资源除(html/js/css)
{
//exclude 排除哪些资源不进行file-loader处理
exclude:/\.(css|js|html)$/,
loader:'file-loader'
}
]
}
}
- 常用的webpack占位符
placeholders | 描述 |
---|---|
hash:10] | 取图片的hash的前10位 |
[ext] | 文件原来的扩展名 |
[name] | 处理文件的名称 |
[contentHash] | 在file-loader中和[hash]结果是一致的(在webpack的一些其他地方不一样,后面会讲到) |
[hash: | 截图hash的长度,默认32个字符太长了 |
[path]: | 文件相对于webpack配置文件的路径 |
- 运行打包命令后build目录下会多出三张图片,这个时候运行build/index.html背景图片和img图片已经生效
7.devServer
- DevServer 是webpack开发服务器;首先,下载webpack-dev-server库
npm i webpack-dev-server@3.10.3 -D
module.exports = {
//刚刚的代码...
devServer:{
// 自定义端口号
port:7000,
//在DevServer第一次构建完成时,自动用浏览器打开网页
open:true,
//配置项用于打开指定 URL 的网页
//openPage: '',
//gzip压缩
compress:true,
//运行项目的目录
contentBase:path.resolve(__dirname,'build'),
//当您有一个单独的API后端开发服务器,并且想要在同一个域上发送API请求时,则代理这些 url
//proxy:{},
//devServer.allowedHosts 配置一个白名单列表,只有HTTP请求的HOST在列表里才正常返回
allowedHosts:[]
}
}
- 运行打包命令,成功后会自动打开浏览器
npx webpack-dev-server
8.打包时将css提取为单独css文件
- 下载所需插件 mini-css-extract-plugin
npm i mini-css-extract-plugin@0.9.0 postcss-loader@3.0.0 postcss-preset-env@6.7.0 -D
- 继续配置webpack.config.js 使用MiniCssExtractPlugin.loader 取代style-loader 提取js中css成单独文件以及处理css兼容性处理:postcss 需要下载 postcss-loader postcss-preset-env 帮助postcss找到package.json中的browserslist里面的配置,通过配置加载指定的css兼容样式
//刚刚的代码...
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
//刚刚的代码...
module: {
rules: [
{
test: /\.css$/,
use: [
// 'style-loader',
//MiniCssExtractPlugin.loader 取代style-loader 作用 提取js中css成单独文件
MiniCssExtractPlugin.loader,
'css-loader'
]
},
//使用 postcss-loader的默认配置
// 'postcss-loader'
//自定义配置
{
loader:'postcss-loader',
options:{
ident:'postcss',
plugins:()=>[require('postcss-preset-env')()]
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
// 将css代码输出到build/css文件夹下
filename:'css/main.css'
})
],
}
-
在package.json中添加配置browserslist 设置语法:通过浏览器过滤的思路实现 默认是兼容所有最新版本
选项 描述 “> 1%” 全球超过1%人使用的浏览器 “> 5% in US” 指定国家使用率覆盖 last 2 versions 所有浏览器兼容到最后两个版本根据CanIUse.com追踪的版本 Firefox ESR 火狐最新版本 Firefox > 20 指定浏览器的版本范围 not ie <=8 方向排除部分版本 Firefox 12.1 指定浏览器的兼容到指定版本 unreleased versions 所有浏览器的beta测试版本 unreleased Chrome versions 指定浏览器的测试版本 since 2013 2013年之后发布的所有版本 not dead 已经寄了的浏览器
//package.json
"browserslist":{
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
}
9.整体代码
//webpack.config.js webpack的配置文件
//作用:指示webpack 干哪些活(当你运行webpack指令时 会加载里面的配置)
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const {
// CleanWebpackPlugin
// } = require('clean-webpack-plugin');
module.exports = {
//entry 入口起点 指示webpack以哪个文件开始打包
entry: './src/index.js',
//output输出 打包后输出到哪去
output: {
// 打包后的文件名称
filename: 'js/main.js',
// 打包后的文件在那个文件夹下; resolve 用来拼接绝对路径
path: path.resolve(__dirname, 'build'),
},
// loader的配置
module: {
rules: [
//详细的loader配置
//不同文件需要配置不同loader处理
{
//test:匹配哪些文件
test: /\.css$/i,
//use:使用哪些loader进行处理
//注意 use数组中loader执行顺序:从右到左,从下到上 以此执行
use: [
//style-loader 的功能就一个,在 DOM 里插入一个 <style> 标签,并且将 css 写入这个标签内
"style-loader",
//css-loader 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
"css-loader"
]
},
// {
// test: /\.css$/,
// use: [
// // 'style-loader',
// //MiniCssExtractPlugin.loader 取代style-loader 作用 提取js中css成单独文件
// MiniCssExtractPlugin.loader,
// 'css-loader'
// ]
// },
// //使用 postcss-loader的默认配置
// // 'postcss-loader'
// //自定义配置
// {
// loader:'postcss-loader',
// options:{
// ident:'postcss',
// plugins:()=>[require('postcss-preset-env')()]
// }
// }
{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
//将less文件编译成css文件
//需要下载less-loader和less
'less-loader'
]
},
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
//图片小于8kb就会转换成base64处理
//优点 减少服请求
//缺点 图片体积更大
limit: 8 * 1024,
//需要将esModule:false 不然解析时会出现问题[object Module]
// 关闭url-loader的es6模块化 使用commonjs解析
esModule: false,
//给图片重命名
//[hash:10]取图片的hash的前10位
//[ext]去文件原来的扩展名
name: '[hash:10].[ext]',
//图片打包后输出的路径 在imgs文件夹内
outputPath:'imgs'
}
},
{
test: /\.html$/,
//处理HTML中的img图片(负责引入img,从而能被url-loader进行处理)
loader: 'html-loader'
},
// 打包其他资源除(html/js/css)
{
//exclude 排除哪些资源不进行file-loader处理
exclude: /\.(css|js|html|less|jpg|png|gif|)$/,
loader: 'file-loader',
options: {
name: '[hash:8].[ext]'
}
}
]
},
//plugins配置
plugins: [
// html-webpack-plugin 默认会创建一个空的html文件
// 功能 自动引入打包输出的所有资源(js/css)
new HtmlWebpackPlugin({
//以src目录下的index.html作为模板
template: './src/index.html'
}),
// 每次打包前自动清除旧的build
// new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
// 将css代码输出到build/css文件夹下
filename:'css/main.css'
})
],
// 打包环境
mode: 'development', //开发环境
// mode:'production' //正式环境
// 开发服务器 devServer:用来自动化编译
//特点:只会在内存中编译打包,不会有任何输出
//启动devServer指令为:webpack-dev-server
devServer: {
// 自定义端口号
port: 7000,
// 自动打开浏览器
open: true,
//gzip压缩
compress: true,
//运行项目的目录
contentBase: path.resolve(__dirname, 'build')
}
}