webpack笔记

| 字数 2043

  
webpack 2.0 用了小一个月了,一直都是照猫画虎。这俩天开始细读官网的部分文章结合一些讲解视频,深入学习一下。小结一发来汇总知识点。   

  1. webpack 的由来?

已存在的模块打包器对于大型应用(大型的SPA)来说并不适合。发展另一个模块打包器最迫切的原因那就是代码分割(Code Splitting)并且可以让静态资源能够无缝的适用于模块化。

  1. webpack 可以做的事情?
  • 将项目间的依赖分割成代码块并按需加载
  • 将初始化载入时间保持在最低
  • 每一个静态资源都应被作为一个模块
  • 有将第三方的库整合为模块的能力
  • 有定制模块的能力
  • 适合大型的单页应用
    -
  1. webpack 的特点有?
  • 代码分割:webapck 在它的依赖树中有俩种依赖关系,同步与异步!异步依赖可以分割成许多不同的点(部分)并且这些依赖来自于新的代码块。在块级树生效后,一个文件会被传递给每一个代码块。
  • 加载器:webpack 是唯一的与生俱来就具有处理 JS 代码的能力,但是加载器被用来将其他源文件转换为 JS 文件。这样来做我们就可以处理来自不同模块的源文件。
  • 智能解析:webpack 可以智能解析第三方库文件。它甚至允许在依赖中出现解释性的描述例如:require("./templates/" + name + ".jade")。具有 CMD&AMD&es6 三种处理模式。
  • 插件系统:webpack 最有特点的就是它生态丰富的插件系统。许多内部的特性都建立在这个插件系统之上。它允许你定制你自己的需求并且可以将其开源。

以上是我对 what-is-webpack 的部分翻译,这些对于快速了解 webpack 来说足够了。

总所周知对于自动化构建这部分来说,我们可以使用的工具很多,比如:grunt 、gulp 等,那么这俩者与 webpack 有什么区别呢?

Grunt&Gulp 是流程工具,其工作方式是在一个配置文件中,指明对某些文件进行的操作(诸如编译,组合,压缩等任务)的具体步骤,之后可以自动完成这些任务。流程如下:

WebPack则是一个模块打包器,其工作方式通过主文件(index.js)找到全部依赖(自己设置的代码块、第三方库等)使用loaders 处理,最终打包为可执行的
Javascript 文件。流程如下:

下面通过实例来看看 webpack 的威力。

1> 简单使用

1
2
3
4
mkdir webpack-1
cd webpack-1
npm init
npm install -d webpack --save-dev

安装完 webpack 2.0 后,新建 js&html&css 文件我的目录如下:

hello.js 中的代码如下:

1
2
3
4
5
6
7
8
require('./world.js');
require('./style.css');

function hello () {
alert('test!');
}

hello();

style.css 中的代码如下:

1
2
3
4
5
6
7
html , body{
padding: 0;
margin: 0;
}
body{
background-color: red;
}

在 webpack 能做的事情中我们了解到 webpack 具有识别 js 的能力,那
css 呢?答案是不能!那怎么解决呢?利用 loaders 来处理。对于 css 文件我们使用 css-loader&style-loader 先利用 npm 分别安装。之后在当前目录下打开 cmd 键入以下命令:webpack hello.js hello.bundle.js --module-bind css=style-loader!css-loader --watch module-bind 命令用于启用 loader 处理主文件,watch 用来监视 hello.js 文件的变化,若变化则自动更新 hello.bundle.js 文件。

  在项目中我们如果每次都要敲一长串命令的话很麻烦,我们只需要在package.json 的 script 中配上 webpack 命令。我得配置如下: "webpack": "webpack --config webpack.config.js --progress --display-modules --colors --display-reasons" 其中 progress&modules&reasons分别代表过程百分比 / 各模块 / 打包原因。

  我们可以将webpack的配置单独放在一个配置文件(webpack.config.js)中会自动读取该文件,如果该文件不存在或者名称不一致则需要通过命令行来运行(不存在的话通过 webpack 命令,名称不一致通过–config 来指定文件)。

  对于 webpack 来说入口与出口肯定是必不可少的,那么在配置文件中我们这样写:

1
2
3
4
5
6
7
module.exports = {
entry: './src/index.js', // entry: ['./src/index-1.js' , './src/index-2.js'] 多入口
output: { //配置文件输出位置
filename: 'bundle.js',
path: './dist/js'
}
};

还有 entry 传入对象的形式入口:

1
2
3
4
5
6
7
8
9
10
module.exports = {
entry:{
main1: './src/index1.js',
main2: './src/index2.js'
},
output: { //配置文件输出位置
filename: '[name]-[chunkhash].js', // 这里如果还这样写filename: 'bundle.js'的结果是index2会把index1覆盖,所以我们利用内置的占位符 name & chunkhash 来命名
path: './dist/js'
}
};

这样的话在 index.html中引入的 js 文件名我们不可能每次打包完都要手动修改,这样很麻烦。所以我们需要使用插件来自动帮我们设置。npm install html-webpack-plugin 安装后修改配置文件为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: {
main: './src/scripts/main.js',
mainA: './src/scripts/mainA.js'
},
output: { //配置文件输出位置
filename: '[name]-[chunkhash]-bundle.js' //打包的文件名称*/
path : './dist',
filename: 'js/[name]-[chunkhash].js', //把html与js分开存放
publicPath: 'http://bluespace/' //上线地址的绝对路径,自动替换当前项目中相对路径
},
plugins: [
new htmlWebpackPlugin({
//filename: '[hash].index.html', //名称
template: 'index.html', //以什么为模板,一般以配置文件下的index.html为模板
//inject: 'head' //scripts存放的位置
title: 'webpack is good!',
inject: false,
date: new Date(),
minify: { //压缩html文件,去除空格,去除注释
collapseWhitespace: true,
removeComments: true
}
})
]

};

而 index.html 模板的代码如下(html-webpack-plugin支持ejs写法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title%></title>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry%>"></script> <!-- 把脚本分开放 -->
<!-- htmlWebpackPlugin.options.date -->
</head>
<body>
<em><%= htmlWebpackPlugin.options.date%></em>
<script src="<%= htmlWebpackPlugin.files.chunks.mainA.entry%>"></script><!--如果想更加优化的话为了减少一次post请求,这里可以直接把script代码放进来,方法如下:
<script>
<%=
compilation.assets[htmlWebpackPlugin.files.chunks.mainA.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source()%>
</script>-->
</body>
</html>

2> 利用 htmlwebpackplugin 构建多页应用 (已上传至 i7eo-github
3> 配置常见的 loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
var htmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');

module.exports = {
entry: './src/app.js',
output: {
path: './dist',
filename: 'js/[name].bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: [{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}],
include: path.resolve(__dirname , './src'),
exclude: path.resolve(__dirname , './node_modules') //尽量使用绝对路径会提高打包速度在configruation里面通过exclude和include来提高打包速度

},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 }
},
{
loader: 'postcss-loader',
options: {
plugins: function(){
return [
require('autoprefixer')
];
}
}
}
]
},
{
test: /.\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: function(){
return [
require('autoprefixer') // postcss下的自动补全浏览器前缀的插件
];
}
}
},
'less-loader' //使用less或者sass时不用为@import的less/sass添加importLoaders:1因为自动添加。因为less/sass支持import
]
},
{
test: /\.html$/,
use: 'html-loader' // 将html当做字符串处理,对应innerhtml。坏处是不能使用for等模板语法
},
{
test: /\.ejs$/,
use: 'ejs-loader' // 把html当做模板处理
},
{
test: /\.(png|jpg|gif|svg)$/i, //用包管理工具除了模板外的文件放置相对路径没有问题,但是在模板文件中应该![](${require('../../assets/George.jpg')})
use: [
{
loader: 'url-loader', //url-loader可以设置limit若图片体积小于limit的话则通过url-loader转化为base64代码,若大于则调用file-loader
options: {
name: 'assets/[name]-[hash:5].[ext]',
limit: 4000 //经常需要加载的图片利用http请求较好,因为可以享受到缓存,而base64则需每次读取
}
},
'image-webpack-loader' //压缩图片体积
]
}
]
},
plugins: [
new htmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: 'body'
})
]
};

参考资料:

webpack

入门webpack,看这篇就够了

html-webpack-plugin