接着上一块https://juejin.im/post/5be29710e51d457e90193cf3
模块:CSS文件打包
Webpack在生产环境中有一个重要的作用就是减少http的请求数,就是把多个文件打包到一个js里,这样请求数就可以减少好多。在学习CSS打包之前,需要先对webpack.config.js里的Loaders配置项进行了解。
Loaders(以下所有的配置都是基于3版本的 如果过程中有bug 会进行改进)
Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以的脚本和工具,从而对不同的文件格式进行特定处理。
简单的举几个Loaders使用例子:
可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
可以把React中的JSX转换成JavaScript代码。
注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。下面我们对Loaders的配置型简单梳理一下。
test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
query:为loaders提供额外的设置选项(可选)。
打包CSS文件
建立index.css文件 ./src/css/index.css
要打包CSS你必须先要有个CSS文件,在/src目录下,我们建立一个css文件夹,在文件夹里建立index.css文件。代码内容如下
body{
background-color: red; 可以跟我不一样 完全为了测试
color: white;
}
CSS文件建立好后,需要引入到入口文件中,才可以打包到,这里我们引入到entry.js中。
/src/entery.js中在首行加入代码:
import css from './css/index.css';
也就是在entry.js中顶部导入
import css from './css/index.css';
document.getElementById('title').innerHTML='Hello Webpack';
CSS和引入做好后,我们就需要使用loader来解析CSS文件了,这里我们需要两个解析用的loader,分别是style-loader和css-loader
首先我们先使用npm 安装(有些脚手架生成的webpack 会自动安装这些简单的加载器)
npm install style-loader css-loader --save-dev
一步到位
安装好之后查看一下package.json
两个loader都下载安装好后,我们就可以配置我们loaders了。
loaders配置:
修改webpack.config.js中module属性中的配置代码如下:
webpack.config.js
const path = require('path')
module.exports={
mode: 'development',
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [ =>以前此处是loaders 现在是rules
{
test: /\.css$/, =>正则 这个好理解
use: [ 'style-loader', 'css-loader' ] =>使用css 与 style loader 来加载匹配到的css文件
}
]
},
//插件,用于生产模版和各项功能
plugins:[],
//配置webpack开发服务功能
devServer:{
host:'localhost', //服务器的ip地址
port:1573, //端口
}
}
webpack一下,之前我们在js中引入了css 运行一下html ok 有样式了
友情提示:小伙伴们在测试的时候,可能会遇到找不到模块的 这种error 建议重新新建配置 重新npm插件 刚才我就莫名其妙找不到模块了 重新安装了一下就可以了
loader的三种写法:
有些小伙伴看到别人的CSS打包的写法和我的写法不太一样,是不是我写错了,loader还有几种写法,这里我们就看两种另外的写法。
使用use
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
},
把use换成loader。
module:{
rules:[
{
test:/\.css$/,
loader:['style-loader','css-loader']
}
]
},
第三种写法:用use+loader的写法:
module:{
rules:[
{
test:/\.css$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader"
}
]
}
]
},
没有全测 也不知道哪里需要修改 小伙伴可以自行测试一下
接下来我们来试着压缩一下js
在Webpack中可以很轻松的实现JS代码的压缩,它是通过插件的方式实现的,这里我们就先来引入一个uglifyjs-webpack-plugin(JS压缩插件,简称uglify)。
注意:虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装。
const path = require('path')
const webpack =require('webpack') =>注意这里我们引入了webpack
module.exports={
mode: 'development',
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
new webpack.optimize.UglifyJsPlugin() =>因为是webpack集成的 所以要在上方引入webpack
]
}
此时我们webpack一下 你会发现 报错(报错的内容就不截屏了)
在webpack4.0版本中已经废弃了之前 UglifyJsPlugin的用法,用的是optimization.minimize
重新配置一下webpack
const path = require('path')
删除了webpack模块引入
const UglifyJsPlugin=require('uglifyjs-webpack-plugin');=>需要 npm 手动安装
module.exports={
mode: 'development',
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
],
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: false
}
})
]
},
}
这里需要注意一下 webpack打包也是分模式的 默认是mode ‘production(生产环境)’
如果我们没在config.js中标明webpack 的mode 直接webpack是会有警告的
就是说我们打包的命令完整应该是 webpack --mode production/development
默认是production 此方法打包文件会小很多 注意一下即可
production 其实默认自带了uglifyjs-webpack-plugin 插件 已经不需要使用
也就是我们在production 状态下 其实可以不需要配置 直接 webpack --mode development 即可
接下来我还是设置默认 production 环境下测试 方便点
插件配置:HTML文件的发布
webpack 构建项目时, 通过指定的入口文件,会将所有的js css 等以依赖模块的形式打包成一个或多个的脚本文件,通常情况下,脚本文件会附属于html 文件运行,这时候需要将 打包好的脚本文件,注入到html 中, html-webpack-plugin 插件的目的是, 以一个html 为模板, 将打包好的脚本注入到模板中, 相关的配置如下
先安装 html-webpack-plugin
npm i html-webpack-plugin -D
安装好之后 我们在plugins中配置
const path = require('path')
const htmlPlugin = require('html-webpack-plugin'); =>引入模块
module.exports={
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
new htmlPlugin({ =>这是一般情况下的配置 打包html
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
})
],
}
minify:是对html文件进行压缩
hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
template:是要打包的html模版路径和文件名称。
此时我们webpack --mode production
此时dist下生成了 index.html js是上面的命令生成的 这就是我们常见的状态了 熟悉vue的小伙伴都知道 npm run build就会生成这俩文件 此时我们直接开index.html 也是有效果的 如果需要改名的话可以再配置一个参数 filename:‘filename.html’ 一定要加后缀
图片迈坑:CSS中的图片处理
在学习Webapck过程中你可能遇到的第一个坑就是CSS中的图片处理。很多webpack新手都在图片的坑中无法自拔(有的小伙伴在开发环境中是可以找到图片的,但是一打包后就找不到图片了,有的小伙伴是不知道如何正确引入html或者css中的图片,导致程序出错)
图片写入css 我们先找张图片先 http://img1.imgtn.bdimg.com/it/u=198855387,108109132&fm=26&gp=0.jpg
注意一定要本地图片啊 刚才偷懒使用网络图片发现居然成功了 不能成功 一定要失败的
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack</title>
</head>
<body>
<div id="tupian"></div>
<script src="./../dist/bundle.js"></script>
</body>
</html>
index.css css还是在js中引入
#tupian{
background-image: url('./../image/1.jpg');
width:466px;
height:453px;
}
我们这时候 通过webpack --mode production 是会失败的 失败的原因就是缺少loader的解析
对于图片我们也需要安装两loader
安装file-loader和url-loade
npm install --save-dev file-loader url-loader
file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。
安装好之后我们来配置webpack 直接在module中配置loader
const path = require('path')
const htmlPlugin = require('html-webpack-plugin');
module.exports={
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
test: /\.css$/, => css的loader
use: [ 'style-loader', 'css-loader' ] =>这边顺带提一下 其实webpack的loader是从右往左看
=>也就是 先使用css loader 再使用style loader
},
{
test:/\.(png|jpg|gif)/ , =>图片的loader
use:[{
loader:'url-loader',
options:{
limit:500000 =>不认识limit的小伙伴可以自行百度一下 类似我们的流量 哈哈 好吧其实就是指500000B
}
}]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
new htmlPlugin({
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
})
],
}
接下来我们webpack --mode production 即可 成功生成
为什么只使用了url-loader
有的小伙伴会发现我们并没有在webpack.config.js中使用file-loader,但是依然打包成功了。我们需要了解file-loader和url-loader的关系。url-loader和file-loader是什么关系呢?简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:
1.文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);
2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。
也就是说,其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上file-loader。
###图片迈坑:CSS分离与图片路径处理
CSS分离:extract-text-webpack-plugin
有些简单的交互页面中,你的JavasScript页面代码会非常少,而大部分代码都在CSS中,这时候项目组长会要求把CSS单独提取出来,方便以后更改。遇到这个需求你不要惊慌,已经有大神为我们准备好了对象的插件(plugin)
这个插件就可以完美的解决我们提取CSS的需求,但是webpack官方其实并不建议这样作,他们认为CSS就应该打包到JavasScript当中以减少http的请求数。但现实中的需求往往不是我们前端能控制的,有些需求是我们不能控制的,分离CSS就是这样一个既合理由不合理的需求,说白了,还是得听老大的 ,如果小姐姐让你这样你做不做呢?
npm install --save-dev extract-text-webpack-plugin
安装好了自然要用 我们直接在webpack上方 引入 const extractTextPlugin = require("extract-text-webpack-plugin")
引入之后 我们只需在webpack中new 使用 并且还要配置关于css的加载器
const path = require('path')
const htmlPlugin = require('html-webpack-plugin');
const extractTextPlugin = require("extract-text-webpack-plugin")
module.exports={
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径位置
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
// test: /\.css$/,
// use: [ 'style-loader', 'css-loader' ]
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test:/\.(png|jpg|gif)/ ,
use:[{
loader:'url-loader',
options:{
limit:500000
}
}]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
new htmlPlugin({
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
}),
new extractTextPlugin("/css/index.css") =>注意插件的使用 (此处是生成的文件位置 前面配置了path 默认都是dist文件下的)
],
}
此时我们webpack一下 是有错误的 因为extract-text-webpack-plugin 不支持4版本以上的
我们既然学习4版本的webpack肯定不能降级 好 我们升级
npm install --save-dev extract-text-webpack-plugin@4.0.0-beta.0
安装好之后 其余不变 再次 webpack一下 因为此时生成打包了三个文件 我给截图一下
这样就成功分离了 本来是起初我们导入js中的 此时成功生成了index.css 并且里面的url是base64形式的,但是我们此时浏览dist下的html是没有东西的 因为我们路径有问题 这里是指图片路径 不是文件路径
图片路径问题
利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确,很多小伙伴就在这里搞个几天还是没有头绪,网上也给出了很多的解决方案,我觉的最好的解决方案是使用publicPath解决
publicPath:是在webpack.config.js文件的output选项中,主要作用就是处理静态文件路径的。
此处增加一个知识 webpack-dev-server 本来是不想配置后面给大家简单提一下,毕竟单独测试webpack的真的不多,很多时候都是看webpack或者脚手架生成直接修改
测试publicPath的时候 没设置服务器状态老报错 使用live-server也不好配置 所以简单提一下webpack-dev-server的配置
npm install webpack-dev-server –save-dev
先安装
在webpack.config.js 中配置
plugins:[
new htmlPlugin({
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
}),
new extractTextPlugin("/css/index.css")
],
devServer:{ =>注意 与plugins同级
//设置基本目录结构
contentBase:path.join(__dirname,'dist'),
//服务器的IP地址,可以使用IP也可以使用localhost
// 不知道自己IP的可以 打开cmd 输入ipconfig 查看
host:'localhost',
//服务端压缩是否开启
compress:true,
//配置服务端口号
port:1717
}
在packge.json的 scripts 中输入"dev": "webpack-dev-server --open"
我们启动webpack-dev-server的时候只需要npm run dev 即可
启动webpack-dev-server之后 会启动热更新 当我们改变内容保存的时候会自动进行webpack命令打包 实时更新内容
别忘了我们主要的目的 ,解决图片路径问题 使用publicPath
主要看output模块
const path = require('path')
const htmlPlugin = require('html-webpack-plugin');
const extractTextPlugin = require("extract-text-webpack-plugin")
module.exports={
// mode:'development',
//入口文件的配置项
entry:{
//里面的entery是可以随便写的
entry:'./src/entry.js',
},
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js',
publicPath:'localhost:1717'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
// test: /\.css$/,
// use: [ 'style-loader', 'css-loader' ]
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test:/\.(png|jpg|gif)/ ,
use:[{
loader:'url-loader',
options:{
limit:500000
}
}]
}
]
},
//插件,用于生产模版和各项功能
plugins:[
new htmlPlugin({
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
}),
new extractTextPlugin("/css/index.css")
],
devServer:{
//设置基本目录结构
contentBase:path.resolve(__dirname,'dist'),
//服务器的IP地址,可以使用IP也可以使用localhost
host:'localhost',
//服务端压缩是否开启
compress:true,
//配置服务端口号
port:1717
}
}