什么是 Webpack?
简单来说,Webpack 就是一个针对 JavaScript 代码的模块打包工具。
工作方式的对比
gulp:
webpack
gulp是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译 替代手工实现自动化工作
如果我们日常使用的时候,不需要使用模块化这个概念,开发的JS随便在一个JS里就OK的情况,或者没有什么联动性的作用,可以使用sublime+gulp+browersync+babelwebpack利用模块化的概念,基本上统统都用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.jsimport 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.jsclass 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.htmlmodule.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给改掉<script src="http://localhost:8080/bundle.js"></script>
,任意改动文件,就可以看到效果了。这个时候,有的同学说自己记不住这个命令怎么办。那么就把这命令写进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
//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是弱类型可以不带,这个不带回报错的。
.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
即可