webpack总结
一、Webpack 是什么?
webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。 简单说就是模块加载器,通过使用Webpack,能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。
二、为什么需要打包?
-
像sass,JSX等代码虽然极大的提高了开发效率,但是本身并不被浏览器所识别,需要我们对其进行编译和打包,变成浏览器识别的代码
-
模块化(让我们可以把复杂的代码细化为小的文件)
-
优化加载速度(压缩和合并代码来提高加载速度,压缩可以减少文件体积,代码合并可以减少http请求)
-
使用新的开发模式
三、webpack主要特性
-
同时支持CommonJS和AMD模块(对于新项目,推荐直接使用CommonJS);
-
串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持;
-
可以基于配置或者智能分析打包成多个文件,实现公共模块或者按需加载;
-
支持对CSS,图片等资源进行打包,从而无需借助Grunt或Gulp(browserify只能打包JS文件);
-
开发时在内存中完成打包,性能更快,完全可以支持开发过程的实时打包需求;
-
对source map有很好的支持。
四、配置(webpack.config.js文件)
var webpack = require('webpack');
var path = require('path');
var SpritesmithPlugin = require('webpack-spritesmith');
module.exports = {
// context: __dirname + '\\app', //上下文
entry: path.resolve(__dirname, 'app/index.js'), //入口文件
output: { //输出文件
path: path.resolve(__dirname, 'app/build/script'),
filename: 'bundle.js'
},
module: {
loaders: [ //加载器
{test: /\.html$/, loader: 'raw'},
// {test: /\.css$/, loader: 'style!css!postcss'},
{test: /\.css$/, loader: 'style!css'},
// {test: /\.(png|jpg|ttf)$/, loader: 'url?limit=8192'}
{test: /\.(png|jpg|ttf)$/, loader: 'file!url?limit=8192'}
]
},
// postcss: function () {
// return [autoprefixer];
// },
plugins: [ //插件
new webpack.BannerPlugin('This file is created by shiddong.'),
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'app/images/'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'app/build/images/sprite.png'),
css: path.resolve(__dirname, 'app/build/css/sprite.css') //产生的样式文件,图片的样式类名是 icon-图片名
},
apiOptions: {
cssImageRef: '../images/sprite.png'
},
spritesmithOptions: {
algorithm: 'top-down'
}
})
]
};
五、webpack.config.js 配置详解
(1)entry
入口文件,可以传字符串,那说明入口文件只有一个;也可以传数组或对象,指定多个入口文件。
有两种语法:
先require path,再利用reslove方法对路径进行解析。
var path = require('path');
entry: path.resolve(__dirname, 'app/index.js'), //入口文件 先定义好上下文路径,那么entry中的路径直接在这个路径下开始
context: __dirname + '\\app', //上下文
entry: './index.js', //入口文件
注:webpack中引入的path是nodejs内置的package,用来处理路径 —— 参考菜鸟教程node.js工具模块。
当entry是数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器,webpack-dev-server。webpack-dev-server会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:
entry: [
'webpack/hot/only-dev-server',
'./js/app.js'
]
当entry是个对象的时候,我们可以将不同的文件构建成不同的文件,按需使用。每一个键值对,就是一个入口文件。
备注:当然也有其他的办法,如express框架,在index.html同路径建立一个server.js,然后运行 node server.js即可。
// express 是一个基于Node.js 平台的web应用开发框架 —— 快速、极简、开放
var port = 8000,
express = require('express'),
app = express();
app.use('/', express.static(__dirname));
app.listen(port);
console.log('Now serving http://localhost:' + port + '/index.html');
(2)output
生成打包文件的配置,可以指定path(路径),当有多个入口文件时,还可以使用[name]、[hash]、[chunkhash]等值,来对应替换为入口的文件的配置。
output: { //输出构建后的文件
path: path.resolve(__dirname, 'app/build/script'),
filename: 'bundle.js'
}
当entry中定义构建多个文件时,filename可以对应的更改为[name].js用于定义不同文件构建后的名字。
entry: {
index: 'index.js'
},
output: {
path: './js',
filename: '[name].bundle.js' // [name] 会由entry中的键(这里是index)替换
} (3)module
定义了对模块的处理逻辑,在webpack中,所有的资源都被当做模块。对于不同文件类型的资源,都有对应的loader。
模块的加载相关配置定义在module.loaders中。
loaders: 加载器配置,通过正则表达式去匹配不同后缀的文件名,然后给它们定义不同的加载器。它可以转换项目中的资源文件,比如说给css文件定义串联的两个加载器(!用来定义级联关系),顺序是从右向左使用:
module: {
loaders: [
{ test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{ test: /\.css$/, loader: "style!css" },
{ test: /\.less/, loader: 'style-loader!css-loader!less-loader'}
]
}
其中,exclude: /node_modules/,
exclude,include手动添加屏蔽不需要处理的文件(文件夹)或必须处理的文件(文件夹)
比较常用的loader:
css-loader: 将样式打包成字符串。
style-loader:将样式字符串添加到页面的style标签中
还可以添加用来定义png、jpg这样的图片资源在大于8k时正常打包,小于8k时自动处理为base64图片的加载器:
{ test: /\.(png|jpg)$/,loader: 'url-loader?limit=8192'} 其中,? 表示加载器支持通过查询字符串的方式接受参数。
给css和less还有图片添加了loader之后,我们不仅可以像在node中那样require js文件了,我们还可以require css、less甚至图片文件:
require('./bootstrap.css');
require('./myapp.less');
var img = document.createElement('img');
img.src = require('./glyph.png'); 这样require来的文件会内联到 js bundle中。如果我们需要保留require的写法又想把css文件单独拿出来,可以使用[extract-text-webpack-plugin]插件。
(4)plugins
插件,它可以干很多很多的事情,非常强大,官方提供了很多插件,第三方也可以写插件。对于用到的插件,只需要将插件new出来放到数组中即可。
BannerPlugin 内置插件来实践插件的配置和运行,这个插件的作用是给输出的文件头部添加注释信息。
ProvidePlugin 插件的作用是自动加载jquery模块,也就是说将jquery变成了全局的模块,当然我们需要在index.html中使用script标签导入。
[原因:由于jquery没有模块化的概念,也没有适配webpack,所以我们使用jquery时,需要在index.html中导入,然后使用 ProvidePlugin 插件使其自动加载。]
plugins: [
new webpack.BannerPlugin('This file is created by shiddong.'),
// 此插件会自动加载jquery,解决jquery无法引用的问题
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
window.jQuery: "jquery"
})
]
(5)导入使用
只需要在index.html中导入bundle.js,
