webpack是干什么?
我们每次开发的时候,都需要在页面的head中加载各种js资源,当你加载了jquery和vue全家桶一套以后,你会发现你的页面已经变得非常的臃肿。更别说你还需要要引用一个你自己的index.js文件。
如果你之前接触过sea.js或者require.js的话,你就可以很容易的理解(你没接触过也无所谓)他们的核心思想就是,把所有需要引入的js,都通过一个公用的js文件去加载。并且在这个js文件中赋予一些逻辑性。
所以最后的结果就是,你最后生成的html文件中只会引用一个js文件和一个css文件,这样不但代码变整洁了,页面打开速度也获得了巨大的提升,这就是所谓的前端优化。
webpack就是一个为了解决这个问题而诞生的工具。当然,它绝对没有这么简单,还记得es6吗,还记得less,sass这种高科技语法吗,你直接在html中使用是不行的,因为低端浏览器并不能解析这类语法。但是通过webpack,我们可以集成一个解析器babel来帮助我们实现对这类语法的解析,让低端浏览器实现全兼容。怎么样,webpack是不是很强大?现在让我们更加详细讲解它的奥秘。
如何安装
webpack是基于nodejs语言的,你不会nodejs也没用关系,因为他只有几个简单的命令。
先从nodejs的官方网站下载nodejs,安装完毕以后,打开doc窗口输入:
npm -g i webpack@3.8.1
安装完毕查看一下版本号。
如果能正确显示版本号,说明安装成功!
创建项目
创建一个你想要作为项目的文件夹,然后在这个文件夹上shift+右键在弹出的菜单中选择打开powershell,这个东西是原来那个doc窗口的加强版,功能跟小黑窗一模一样。然后输入:
npm init
你会看到很多需要你输入的东西,不用管,一路回车。
这一步的主要目的是创建一个基于npm的项目,以后,我们安装任何插件,只需要配置这个项目中的package.json文件即可。如果你之前没有使用过npm,你到这一步的时候可能会有点蒙,不要着急,我们继续往下,龙哥的文章向来就是即插即用,就算你不会安装,你把我给你的例子一拷贝,你也可以实现webpack的各种操作,原理什么的你在实战中逐渐体会也完全没问题。
接着你用编辑软件打开刚才输入命令的那个文件夹,你会发现里面有一个package.json文件,改成我这个样子:
{
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-runtime": "^6.26.0",
"autoprefixer": "^7.2.3",
"css-loader": "^0.28.7",
"style-loader": "^0.21.0",
"less-loader": "^4.1.0",
"url-loader": "^0.6.2",
"file-loader": "^1.1.6",
"html-webpack-plugin": "^2.30.1",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.7",
"webpack-require-http": "^0.4.3",
"extract-text-webpack-plugin": "^3.0.2"
},
"name": "demo",
"version": "1.0.0",
"main": "webpack.js",
"dependencies": {
"bootstrap": "^3.3.7",
"html-loader": "^0.5.5",
"jquery": "^2.1.1",
"less": "^3.0.4",
"less-loader": "^4.1.0",
"style-loader": "^0.21.0",
"webpack-dev-server": "^2.11.5"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"dev": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"description": "",
"babel": {
"presets": [
"es2015",
"react"
]
}
}
刚才我们说了,这个文件主要的作用是,npm在你这个项目中,使用哪些插件。你仔细看我这个文件,里面已经包含了es6解析器,css和less,url图片地址等等各种解析器,甚至规定了webpack的版本。
然后输入一遍
npm install
这一步操作的目的是把配置文件中的内容安装到本地。
webpack.config.js的配置
接着在package.json的同级目录下创建一个webpack.config.js,这个文件的目的主要是为了配置我们的webpack。
像我这样写:
// 引入webpack
const webpack = require('webpack')
// 引入html生成插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入css压缩插件
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
// 入口文件,指向app.js
entry: {
index: './src/js/index.js',
},
// 出口文件
output: {
// 项目的路径
path: __dirname + '/dist',
// 增加随机数防止缓存
//filename: 'js/[name].[hash:5].js',
// 输出的文件的路径
filename: 'js/[name].js',
// 为使用热启动后产生的日志文件设定输入路径
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
},
externals:[
// 让webpack可以加载外部http资源 例如螳螂
require('webpack-require-http')
],
// webpack-dev-server 环境
devServer: {
contentBase: './dist',
hot: true
},
module: {
// loader放在rules这个数组里面
rules: [
{
//把es6转换成es5
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.html$/,
use: {
loader: 'html-loader'
}
},
{
//识别图片
test: /\.(png|jpg|gif)$/,
loader: 'url-loader',
options: {
limit: 4096,
name: 'image/[name].[ext]'
}
},
{
//压缩css
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
publicPath: "../",
use: [
{
loader: 'css-loader',
options:{
minimize: true //css压缩
}
}
]
})
},
{
//识别字体文件
test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
},
]
},
// 将插件添加到webpack中
plugins: [
// 开启多页应用 生成html文件
new HtmlWebpackPlugin({
//模板文件是哪个
template: './src/index.html',
//选择注入哪个文件
chunks: ['index'],
//是否添加hash随机数防止缓存
//hash: true,
//开启html压缩
minify:{
removeComments:true, //移除HTML中的注释
collapseWhitespace:true//压缩为一行
},
// manual根据chunks的位置手动排序
chunksSortMode: "manual"
}),
// 防止webpack一直弹出警告 加载HMR需要的两个插件
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
// 解决加载jquery后 jquery不能获得$符控制权的问题
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new ExtractTextPlugin("css/styles.css"),
]
}
你现在肯定有点懵,这是干什么呢??上来一顿配置,我都不知道干什么呢。
不用着急,我们先把开发环境配置好,当我们开始使用的时候,我们会逐个讲解这些配置用到的地方!
到了这一步,你的项目文件夹下面,应该有node_modules文件夹,一个package.json文件和一个webpack.config.js文件,好的,然后你再创建两个文件夹,一个叫src,一个叫dist。
全部完成以后是这样的:
到了这一步,webpack的安装和配置就完成了,接下来我们该进入开发环节了。
如何使用
我们新建的两个目录:dist为生成生产环境,src为开发环境
你所有的操作全部在src中完成,我们的最终目的是:
通过小黑窗口中输入一遍webpack命令,把src中的文件压缩优化成为src文件夹中的最终形态。也就说,我们开发的时候,只需要修改src目录中的内容,正式上线的时候,只需要把dist中的文件通过ftp传到服务器就可以了。
这里龙哥需要给你讲一下原理,现在webpack的教程有很多,但是我相信大部分人到了,入口文件那块就差不多放弃了。因为webpack它本身是基于nodejs的,nodejs顾名思义,只能编译js...
所以,你放在项目里面的html啊,css啊甚至图片啊。nodejs一概不承认,或者你可以理解为,它不认识这是什么。
这里我们就需要编写一个文件,让我们把项目中的所有资源都利用起来,并且告知webpack这些资源都是什么,这个文件,就叫做入口文件。这个文件的配置你可以灵活配置,我自己是选择放在src中的js文件夹中,因为这样让它们看起来更加规范一些。
如果你仔细阅读上面的webpack.config.js文件的话,你会发现,里面的entry项就是入口文件的位置。
然后我们来看看这个文件中都写了一些什么东西:
//引入jquery 必须为此写法让插件和全局都获得jquery支持
import $ from 'jquery'
window.$ = $
window.jQuery = $
export default $
//引用bootstrap
// import 'bootstrap';
// import 'bootstrap/dist/css/bootstrap.css';
//加载自己的js
import '../js/time/flipclock.js';
//引用html加载页面上的src资源
import '../index.html';
//引入自己的css
import '../css/index.css';
import '../js/time/flipclock.css';
你会发现,页面,页面上的css和js都是在这个js文件中被引用的。
此时我的html页面上什么也没有引用。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的标题</title>
</head>
<body>
<article>
我的内容
</article>
</body>
</html>
你可能会好奇,如果我的html中不引入,那么最后打包完了以后,这个js文件会被加载吗?
答案是会的,webpack会自动加载配置文件中的入口文件到你的html中。
这里我忽然想起了一个情况:那就是,有一些时候,我们需要引入外网的资源,这些资源是不能被打包到项目中的,比如一些crm系统,或者一些站长统计的js。
我们需要使用这个方法:
//引入jquery 必须为此写法让插件和全局都获得jquery支持
import $ from 'jquery'
window.$ = $
window.jQuery = $
export default $
//引用bootstrap
// import 'bootstrap';
// import 'bootstrap/dist/css/bootstrap.css';
//加载自己的js
import '../js/time/flipclock.js';
//引用html加载页面上的src资源
import '../index.html';
//加载外网的js
Promise.all([
require('http://talk2.bjmantis.net/chat/js/dist/mantis.min.js?123456'),
require('http://talk2.bjmantis.net/chat/js/dist/register_form.min.js')
]).then(function() {
});
//引入自己的css
import '../css/index.css';
import '../js/time/flipclock.css';
然后让我们来完成这个页面,我添加了一些内容,然后把图片也引入了,当我们感觉编辑的差不多了的时候,在小黑窗中输入:
npm run dev
你会看到这个画面,然后打开窗口中提示的地址就能看到我们的页面。
打包发布项目
当我们感觉页面已经没问题可以打包上线的时候,还是在这个目录上,输入:
webpack
是的,仅仅就需要这么一个单词而已。
然后打开dist目录,你会发现所有的文件webpack已经帮我们打包好了,然后我们把dist目录里面的文件上传到ftp就行了。
webpack常见问题解答
通过上面的学习,我们已经可以通过webpack压缩优化我们的项目了。
但是我想告诉你的是webpack能做的事情远不止如此,我们经过学习,知道了webpack其实是一个打包工具,它把我们项目中用到的插件都合并成了一个js,还可以优化css和img图像。那么,我们常用的插件是哪些?它们又发挥了什么作用?打包出来的页面能否不只是一个spa而是多个页面呢?
常用插件说明(package.json)
package.json中有一项是devDependencies,这一项表示npm包中引用了哪些编译包
插件名称 | 版本号 | 作用 |
---|---|---|
babel-core | 6.26.0 | 编译es6 |
babel-loader | 7.1.2 | 编译es6 |
babel-plugin-transform-runtime | 6.23.0 | 编译es6 |
babel-preset-env | 1.6.1 | 编译es6 |
babel-preset-es2015 | 6.24.1 | 编译es6 |
babel-preset-stage-0 | 6.24.1 | 编译es6 |
babel-runtime | 6.26.0 | 编译es6 |
autoprefixer | 7.2.3 | css3自动添加前缀 |
css-loader | 0.28.7 | 编译css样式表 |
style-loader | 0.21.0 | 编译css样式表 |
less-loader | 4.1.0 | 编译less样式表 |
url-loader | 0.6.2 | 编译图像,能转化为base64就转化,不能转化就通过file插入到页面中 |
file-loader | 1.1.6 | 编译图像,能转化为base64就转化,不能转化就通过file插入到页面中 |
html-webpack-plugin | 2.30.1 | 生成html 否则你的项目最后只会有一个压缩的js |
webpack | 3.8.1 | webpack |
webpack-dev-server | 2.9.7 | 本地环境启动器 |
webpack-parallel-uglify-plugin | 1.1.0 | js压缩工具 |
webpack-require-http | 0.4.3 | 加载外部文件 |
extract-text-webpack-plugin | 3.0.2" | 提取css为一个文件 |
webpack可否通过多个入口文件打包成多个页面,而不是spa
第一步你需要HtmlWebpackPlugin
在webpack.config中配置成这个样子,生成多个页面。
new HtmlWebpackPlugin({
template: './src/index.html',
chunks: ['common', 'index']
}),
new HtmlWebpackPlugin({
filename: 'list.html',
template: './src/list.html',
chunks: ['common', 'list']
}),
new HtmlWebpackPlugin({
filename: 'detail.html',
template: './src/detail.html',
chunks: ['common', 'detail'] //这里是页面中允许加入哪几个js 这里你可以看到require方式的影子
}),
另外就是在入口文件中配置以下就行了。
entry: {
index: './src/js/index.js',
list: './src/js/list.js',
detail: './src/js/detail.js'
},
总结一下
webpack的使用方法就为各位总结到这里啦,极简系列的文章都是龙哥总结的干货。最重要一点讲究即插即用,你完全可以复制本文中的代码到项目中,立刻对你的推广单页或者本地项目做一个优化—webpack可以做的事情远不止我本文中介绍的那些,本文只是介绍使用方法和原理,更多高级玩法还是需要你自己去开发,加油!