写在前面的话:
在当前grunt、gulp、webpack成为日常工具的情况下,如果你还只是熟练的使用html、css和激块瑞的话,已经远远不能满足项目的需求,所以你得变强,你需要懂得更多。现在前端不仅仅是用那几句蹩脚的JavaScript代码在浏览器渲染几个页面然后提交几个表单在写点交互了。现在WebGL协议可以为HTML5 Canvas提供硬件3D加速渲染,你可以用JavaScript语法可以渲染3D模型,你也可以用nodejs搭建后台,还可以用react-native、weex做一个app。js发展的也越来越像后台语言,毕竟js已经将它的魔爪伸到了很多领域,这让你可以猥琐欲为。。。确实每个前端都应该有一统前端界的野心,寄人篱下只是暂时的 ⌒_⌒....
一、webpack安装及概念
webpack是现代JavaScript应用程序的静态模块打包工具
,webpack是通过npm来安装的,npm是跟node一起下载的包管理工具,所以你得保证电脑上已经安装了node。在安装之前先来说下cnpm,因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,那下载速度让人不由得喊一声“王德发”,所以我们‘伟大的’淘宝团队干了一件伟大的事:“这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。” 你只要执行以下命令:
$ npm install -g cnpm
用了cnpm之后那速度让人爽得不要不要的,再也不用担心摔键盘的问题了。
那么下面就来介绍一下webpack的安装,安装包括本地安装和全局安装(我用的是webpack4版本):
全局安装(全局安装是安装到你C盘里,在任何地方都可以使用):
cnpm i webpack -g
本地安装(是安装到当前目录,只能在当前目录使用):
cnpm i webpack -D //i 是install 的缩写
如果你想安装webpack特定的版本,比如说2.2:
cnpm i webpack@2.2 -D
在以前的版本中webpack和webpack-cli是一体的,但在webpack4中,它把webpack和它的cli分开来以方便于管理,所以还需要安装:
cnpm i webpack-cli -D
到这里我们已经怀着美滋滋的心情介绍完webpack的安装方法了,现在介绍一下webpack的基本概念,它的基本概念有四个,是的只有四个,你没有看错(是不是很高兴?你高兴的太早了):
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
我们来简单说一下家伙的功能先李姐李姐:
entry:顾名思义就是入口,就好像一个口袋的袋口,要装东西(比如说一支笔)进去就要通过这里。
output:肯定就是出口啦,你把一个装笔的袋子拿绳子捆起来后放到一个地方,这个地方就是出口。
loader:这个单词的意思是装货的人
,那么在这里就是指的是那个装笔的人,意思是因为笔不可能自己跑进袋子里,需要一个人代劳。其实正确的解释是webpack自身只能理解javascript,它不认识这支笔是什么东西,所以就需要loader告诉webpack这是一支笔,那么webpack就能理解这支笔了。
plugins:这个就是插件,我们对插件肯定很熟悉了,在项目中我们用过很多各种各样的插件,它可以用来处理各种各样的任务。
二、一个简单的项目
介绍完了webpack的安装以及概念,让我们释放一下蠢蠢欲动的心做一个小项目吧:
- 让我们新建一个文件夹
mkdir webpack_lesson_one
- 进入到新建的文件夹内
cd webpack_lesson_one
- 新建一个项目
npm init -y
- 安装webpack以及webpack-cli
cnpm i webpack webpack-cli -D
- 接下来我们在根目录新建一个
index.html
和一个webpack的配置文件webpack.config.js
以及一个资源文件夹src
,完成以上流程以后我们的目录应该是这个样子的:
- 我们在
src
目录里面新建一个入口文件index.js
,然后编辑文件如图:
- 然后我们开始编辑
webpack.config.js
:
const path = require('path');
module.exports = {
entry:{ //入口文件配置,当然这里可以配置多个入口文件,在此对象内增加增加键值对即可
app: './src/index.js'
},
output:{ //出口文件配置
filename:'[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
//path.resolve()是nodejs中的语法,拼接路径, __dirname代表项目根目录
- 修改package.json文件增加
"scripts"
命令,如下:
接下来在根目录的index.html
中引入app.bundle.js
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="dist/app.bundle.js"></script>
</body>
</html>
- 接下来打开终端执行命令:
npm run build
接下来就是见证奇迹的时刻了,你的项目根目录会生成dist
文件夹,浏览器运行index.html
就会看到hello world!
,那么我们的一个超级森破的项目就这样完成了。
三、引入css、图片、字体
在介绍上面几个功能前先说一下项目目录的合理分配,一个合适的项目目录可以降低整体项目的依赖性,大大提高工作中的开发效率,所以资源管理一定做好。那么在src
目录中新建components
目录,然后新建文件如下:
|- /src
|- |- /components
|- | |- /News
|- | |- |- /img
|- | |- |- index.js
|- | |- |- style.css
|- index.js
- 接下来我们呢先安装
style-loader
和css-loader
以及file-loader
:
cnpm i style-loader css-loader file-loader -D
- 下面在
webpack.config.js
中配置:
const path = require('path');
module.exports = {
entry:{
app: './src/index.js'
},
output:{
filename:'[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/.css$/,
use:['style-loader', 'css-loader'] //这里需要注意下,style-loader 必须要写在 css-loader 之前哟
},
{
test:/.(jpg|png|gif|svg)$/,
use:[
{
loader:'file-loader',
options:{
name:'img/'+'[name].[ext]?[hash]', //可以重写css中引入图片部分
publicPath: 'dist/' //可以重新生成图片到新的目录
}
}
]
}
]
}
}
我们来修改src
目录下的index.js
编写News
目录下的style.css
文件
body{
background: #fff url(img/banben.png) 0 0 no-repeat;
}
编写News
目录下的index.js
文件
import './style.css';
console.log('有一天我希望站在这个世界的顶端说出八个大字:我的,我的,都是我的!');
现在你再运行npm run build
命令,再运行index.html
看看是不是这样的效果(啊,多么漂亮的图标啊!):
再看看里面加载的css:
图片后面自动加上了参数,这就是上面的配置项name:'img/'+'[name].[ext]?[hash]'
的作用。你可以去看看file-loader的使用方法,让我们姿势一起涨,1(yao)3(san)一起装。
- 那么引入字体也是同样的道理,编辑
webpack.config.js
文件:
const path = require('path');
module.exports = {
entry:{
app: './src/index.js'
},
output:{
filename:'[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/.css$/,
use:['style-loader', 'css-loader'] //这里需要注意下,style-loader 必须要写在 css-loader 之前哟
},
{
test:/.(jpg|png|gif|svg)$/,
use:[
{
loader:'file-loader',
options:{
name:'img/'+'[name].[ext]?[hash]', //可以重写css中引入图片部分
publicPath: 'dist/' //可以重新生成图片到新的目录
}
}
]
},
{
test:/.(woff|woff2|eot|otf|ttf)$/,
use:['file-loader']
}
]
}
}
- 在
src
目录下新建public
文件夹,放入字体文件资源:
- 在
src
目录下的index.js
引入字体css文件:
- 在
index.html
中添加字体标签:
再去News
里改变一下字体的大小,做人就是要大气一些:
然后再npm run build
一下看看字体图标已经加载出来了!!!
四、图片的压缩以及旧文件的删除
我们已经能加载图片了,那么试着压缩一下吧,毕竟浓缩的才是精华、O(∩_∩)O哈哈~。。另附直通车image-webpack-loader,一条龙式服务必须滴。
还是老样子,当然还是先安装image-webpack-loader
cnpm i image-webpack-loader -D
修改webpack.config.js
module里的rules:
module:{
rules:[
{
test:/.css$/,
use:['style-loader', 'css-loader']
},
{
test:/.(jpg|png|gif|svg)$/,
use:[
{
loader:'file-loader',
options:{
name:'img/'+'[name].[ext]?[hash]',
publicPath: 'dist/'
}
},
{ //压缩图片要在file-loader之后使用
loader:'image-webpack-loader',
options:{
bypassOnDebug: true
}
}
]
},
{
test:/.(woff|woff2|eot|ttf|otf)$/,
use:['file-loader']
}
]
},
现在你npm run build
之后看看dist
文件夹内的banben.png
和之前的图片大小对比,是不是小了一半,就是这么方便。
- 还有我们在做项目时很多时候都需要删除之前废弃的文件。举个栗子:现在我们把上面的
file-loader
里的name
参数变一下:
{
loader:'file-loader',
options:{
name:'img/'+'[hash].[ext]', //把[name] 换成 [hash]
publicPath: 'dist/'
}
}
这样我们生成的文件是一个以哈希值命名的图片,当我们改变原图片名字的时候再打包后会重新生成一个图片文件,但是之前生成的依然还在那里一动不动。这个时候我们就需要用到clean-webpack-plugin了,当然这个是插件
不是loader
哟~ 那就让我们来安装吧:
cnpm i clean-webpack-plugin -D
- 同理配置一下
webpack.config.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin'); //插件是需要引入的,这里可别忘了引入
module.exports = {
entry:{
app: './src/index.js'
},
output:{
filename:'[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/.css$/,
use:['style-loader', 'css-loader']
},
{
test:/.(jpg|png|gif|svg)$/,
use:[
{
loader:'file-loader',
options:{
name:'img/'+'[hash].[ext]',
publicPath: 'dist/'
}
},
{
loader:'image-webpack-loader',
options:{
bypassOnDebug: true
}
}
]
},
{
test:/.(woff|woff2|eot|ttf|otf)$/,
use:['file-loader']
}
]
},
plugins:[
new CleanWebpackPlugin(['dist/img']) //数组内的是需要清理的目录
]
}
来来来,我们npm run build
一下,是不是你的img
文件消失一下后又重新浮现在你的眼前了,如果没有消失过可能是你的眼花了。
当然你还可以设置其它参数,详见clean-webpack-plugin
plugins:[
new CleanWebpackPlugin(['dist/img'],{
exclude: [ 'banben.png' ] //这个配置意思就是不删除 img 文件里面的 banben.png 图片
})
]
现在本期webpack笔记已经到此结束了,另附上github项目练习素材地址:https://github.com/zgf123/web...
五、知识小结
webpack遵循commonJs规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量就是一个对象,它的exports属性就是对外的接口,所谓加载某个模块,其实就是加载这个模块的modules.exports属性。