什么是 Webpack?
简单来说,Webpack 就是一个针对 JavaScript 代码的模块打包工具。
工作方式的对比
gulp:
webpack
gulp是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译 替代手工实现自动化工作
如果我们日常使用的时候,不需要使用模块化这个概念,开发的JS随便在一个JS里就OK的情况,或者没有什么联动性的作用,可以使用sublime+gulp+browersync+babel
webpack利用模块化的概念,基本上统统都用js来写,Webpack的处理速度更快更直接,能打包更多不同类型的文件。
安装
首先创建一个webpackdemo的文件夹,然后命令行进入到该文件夹下,执行npm init
,然后一路回车,输入yes后就可以看到文件夹下的package.json
文件,这也是我们所有包都需要的文件依赖。
//全局安装
npm install -g webpack --registry=http://registry.npm.taobao.org
//安装到你的项目目录
npm install --save-dev webpack --registry=http://registry.npm.taobao.org
先来创建三个文件,一个是html,一个是我们即将使用的主入口文件index.js,一个是我们将要引用的文件person.js
Document
//index.js
import Person from './second';
let app = document.createElement('div');
app.className='MyDiv';
app.innerHTML = 'Hello World,I am the index content
Hi,I am the vice content';
let luren = new Person('张三',18);
document.body.appendChild(app);
console.log(luren.say());
//second.js
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
say(){
return `我是${this.name},我今年${this.age}岁了。`;
}
}
export default Person;
配置webpack.config.js文件
光有了package.json
还不够,为了更方便,不用自己每次都去输入各种命令,还要有webpack.config.js
文件
// entry 入口文件 让webpack用哪个文件作为项目的入口
// output 出口 让webpack把处理完成的文件放在哪里
// module 模块 要用什么不同的模块来处理各种类型的文件
var path = require('path');
//定义了一些文件夹的路径
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'src');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
module.exports = {
//项目的文件夹 可以直接用文件夹名称 默认会找index.js 也可以确定是哪个文件名字
entry: APP_PATH,
//输出的文件名 合并以后的js会命名为bundle.js
output: {
path: BUILD_PATH,
filename: 'bundle.js'
},
//webpack使用loader的方式来处理各种各样的资源/2.0叫rules,区别不是很大,任何文件运行想要解析都需要经过loader
module: {
rules: [
{
test: /\.jsx?$/,//首先先去匹配我们的include文件夹下的包含.js或.jsx后缀名的文件
include: APP_PATH,//目标文件夹
use: ['babel-loader']//使用babel-loader处理这些文件
}
]
},
};
以上就是一个最简单的webpack.config.js配置文件,其中loaders部分里只写了一个babel,就是为了我们能快点先看到东西,所以我们要先装上babelnpm install babel-core babel-loader babel-preset-latest --save-dev --registry=http://registry.npm.taobao.org
。
这里babel-core
顾名思义是babel的核心编译器. babel-preset-latest
是一个配置文件, 意思是转换ES2015/ES2016/ES2017到ES5, 不只ES6. babel还有其他配置文件. 如果只想用ES6, 可以安装babel-preset-es2015:
执行webpack
,我们可以看到build里多了一个文件bundle.js,但是只有文件,这样的话没有服务器也是很麻烦,每次改动都需要手动执行webpack
。而webpack自带的一个强大的功能就是自带开发服务器。
配置webpack-dev-server
npm install webpack-dev-server --save-dev --registry=http://registry.npm.taobao.org
安装完成后,如何使用它呢,肯定是要在配置文件里写上dev-server的配置的
// devserver配置选项 功能描述
// port 设置默认监听端口,如果省略,默认为”8080“
// inline 设置为true,当源文件改变时会自动刷新页面
// colors 设置为true,使终端输出的文件为彩色的
// historyApiFallback 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
module.exports = {
....
devServer: {
host:'0.0.0.0',//有了这个参数,写上0.0.0.0,我们就可以用ip地址访问了,没有的话如果别人访问会被禁止掉的
historyApiFallback: true,
hot: true,
inline: true,
//progress: true, 已经废弃,别写上去
},
...
}
现在配置文件也有了,我们就可以走一把,运行webpack-dev-server --hot --inline
。然后把我们的html文件中的script标签中的src给改掉,任意改动文件,就可以看到效果了。这个时候,有的同学说自己记不住这个命令怎么办。那么就把这命令写进
package.json
里面吧。
// npm的start是一个特殊的脚本名称,它的特殊性表现在,在命令行中使用npm start就可以执行相关命令,
// 如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build
...
"scripts": {
"start": "webpack-dev-server --hot --inline"
},
...
下面是webpack-dev-server里的一些具体参数,可以看看。
添加css和图片处理的loader/rule
npm install css-loader style-loader --save-dev --registry=http://registry.npm.taobao.org
然后修改下webpack.config.js的配置文件
//css-loader会遍历css文件,找到所有的url(...)并且处理
//style-loader会把所有的样式插入到你页面的一个style tag中
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
include: APP_PATH
}
但是现在很多小伙伴又都喜欢使用less
或者是sass
,以less
为例子,运行npm install less-loader less --save-dev --registry=http://registry.npm.taobao.org
,然后再rule中修改正则和use也就是1.x版本中的loaders
{
test: /\.css|.less$/,
use: ['style-loader', 'css-loader','less-loader'],//一旦use参数里的loader是一个数组,记住,执行顺序是从右向左,如果写错了那就会有问题了。
include: APP_PATH
}
css里面也可以模块化的引用其他css,@import 'xxx.less';
,记住,一定要打分号,不像是js是弱类型可以不带,这个不带回报错的。
处理完了css/less,现在我需要引用图片了,怎么办,假如我在样式里写了网络路径的图片,是没有问题的,但是假如我随便写了一个本地路径的图片
.MyDiv{
background: url('./img/smallPic.png');
}
运行会发现报错了,错误信息是
还是很清楚的,它说它需要单独处理该文件的话需要我们弄一个loader也就是rules来处理他们
执行npm install url-loader file-loader --save-dev --registry=http://registry.npm.taobao.org
,然后添加处理图片的loader
{
/*
css-loader引用的图片和字体同样会匹配到这里的test条件
*/
test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
/*
使用url-loader, 它接受一个limit参数, 单位为字节(byte)
当文件体积小于limit时, url-loader把文件转为Data URI的格式内联到引用的地方
当文件大于limit时, url-loader会调用file-loader, 把文件储存到输出目录, 并把引用的文件路径改写成输出后的路径
*/
use: [
{
loader: 'url-loader',
options: {
limit: 10000
}
}
]
},
然后没讲的是css的autoprefix
功能,直接用你的编辑器快速补全吧,很方便的
其他功能
使用webpack2 自带的处理es6
{
"babel": {
"presets": [
[
"latest",
{
"es2015": {
"loose": true,
"modules": false
}
}
]
]
}
使用后运行webpack可以发现bundle文件的行数会变小很多
使用自带的压缩js代码
plugins: [
//这个使用uglifyJs压缩你的js代码,仅限生产环境,否则sourcemap找不到
new webpack.optimize.UglifyJsPlugin({minimize: true})
]
可以看到这里使用了一个新的名词,plugins,就是一旦使用插件类的,都需要在plugins来写,很多写插件的话需要声明一个webpack。
在配置文件的最上面来写var webpack = require('webpack');
;
使用三方库比如jquery
`npm install jquery --save-dev --registry=http://registry.npm.taobao.org`
plugins: [
...
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
...
]
分离第三方库
这个时候会发现我们的bundle.js文件超级大,因为jquery也被打进去了,所以我们需要做拆分工作,把我们引用的三方库给分离出来。
entry: {
app: APP_PATH,
//添加要打包在vendors里面的库
vendors: ['jquery']
},
//输出的文件名 合并以后的js会命名为bundle.js
output: {
path: BUILD_PATH,
filename: '[name].js'
},
plugins: [
...
new webpack.optimize.CommonsChunkPlugin({
names: ['vendors']
})
...
]
再手动把html引用的script给换掉就可以了。
使用source-map
好多模式,该用哪个,开发用cheap-module-eval-source-map
这个绝大多数情况下都会是最好的选择,这也是下版本 webpack 的默认选项。不方便看的话就直接source-map
,就是文件大点
生产
建立生产配置文件webpack.production.config.js
,然后去掉dev的配置,写进package.json
里"build": "webpack --progress --profile --colors --config webpack.production.config.js"
,运行npm run build
即可