关于WMOS
好吧,作为第一个系列第一篇的内容估计没多少人会看,所以大概会写的比较烂,还请看的人见谅。至于关于WMOS是什么,在这篇文章里不是十分重要,就先卖个关子,以后(大概吧)会慢慢跟大家说。这里就先当做一个要做的项目就好了。回到正题。
Webpack
现在的前端开发不同以前,不是写写html,css,js就OK的。随着项目的复杂就会考虑一些工程化的东西,因为如果有很多东西都需要我们自己去做会费很多时间。webpack就是一个类似gulp或者grunt的工具,不过它的核心可不只是自动化这么简单。
版本
目前webpack最新的版本是v3.4.1
,而我也是在此基础上进行学习和开发的。
不直接聊原理
由于我之前也用过webpack并且也深入去学习了原理的东西,不过那个时候的我太年轻所以只是理解然而让我说出个一二三四,大概我会想个好几天(其实就是当时学的不扎实,呜呜)。所以这次做WMOS的目的其实就是在实现的过程中来深刻理解一些之前学过或者学习没接触的东西。这也就是探索式学习。
看文档
我在使用webpack之前,首先看了一下当前的版本,这是一定要注意的事。因为有些api在不同的版本可能有所差异,在之后的使用的时候很有可能成为坑点。
而在看完文档的概念和指南之后,虽然对如何使用有了大致的了解,可是实际使用的话总感觉自己没看一样,emmmmmm。
不过看过文档起码在看别人的webpack配置文件的时候就可以稍微读懂了。
你想做什么
看过很多遍文档(中文)后,发现自己依然没有头绪(挠头)。突然就想到我到底用webpack做什么?用webpack做什么?做什么?这是很重要的一件事,说三遍。
于是我重新开始,想想我目前到底想要什么功能?
WMOS打算使用原生的js写,并且使用ES2015。
使用less预编译器。
能够对图片进行一些处理。
能够热更新
。。。。
貌似目前就只有这些需求,虽然我知道这一定不是全部。但是我认为项目是一点一点搭起来的。目前我还没有达到那种程度,所以一步一步来。
干货来了
说了这么久,是为什么?因为我今天在搭建webpack环境的时候,卡在HtmlWebpackPlugin
,好痛苦~~(>_<)~~。
什么是HtmlWebpackPlugin
官网在它的指南里是这么引出的:
在更改了入口文件的时候,会生成新的文件,而我们的
index.html
文件还是引用旧的问卷。这个时候就要用HtmlWebpackPlugin
。
HtmlWebpackPlugin
简化了HTML文件的创建,以便为您的webpack包提供服务。这对于在文件名中包含每次会随着变异会发生变化的哈希的webpack bundle
尤其有用。 您可以让插件为您生成一个HTML文件,使用lodash模板提供您自己的模板,或使用您自己的loader。·
以上都是官网给出的内容。其实目前我使用之后的感觉就是:可以为我们生产html文件,并且直接把那些生产的bundle
文件直接写入html中。这个在想要实现热更新的时候是很有用的。最后在通过下面的例子在理解一下HtmlWebpackPlugin
。
最初的时候目录是这样的:
你会发现在dist
文件夹下什么都没有,dist
文件夹是我们生产文件的地方,src
文件夹是我们的源文件夹。然后看一下我们的webpack配置文件:
使用过webpack的同学知道,在运行webpack之后应该生产在dist
文件夹里生成main.js
,而这个js文件需要我们手动放入html文件中。不过这里通过HtmlWebpackPlugin
我们就不用手动操作了。让我们执行一下:
原来的index.html
:
现在的index.html
:
下面来详细讲一下HtmlWebpackPlugin
插件。
安装
npm install --save-dev html-webpack-plugin
基本用法
该插件会为您生成一个HTLM5文件,其中会包括使用script
标签引用的js输出文件。最进本的用法就是将插件直接添加到webpack配置中,如下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
entry: 'index.js',
output: {
path: 'dist',
filename: 'index_bundle.js'
},
plugins: [new HtmlWebpackPlugin()]
};
这将会产生一个包含以下内容的文件 dist/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
如果有多个webpack入口,就会生成多个script标签引用这些文件。
如果你有任何CSS assets 在webpack的输出中(例如,利用ExtractTextPlugin提取CSS),那么这些将被包含在HTML head中的<link>
标签内。
配置
下面是HtmlWebpackPlugin
插件的一些配置选项:
title
: 生成的html文档的title
标签之间的内容。filename
: 生成html文件的名字,默认为index.html
。你可以使用子目录的形式,像asset/admin.html
是OK的。template
: webpack会require这个路径的文件作为模板。(我就卡这里了,稍后会详细讲一下)inject
: 它有四个值,分别为true
、head
、'body'、'false',功能是在将所有的资源输出到template
或者templateContent
指定的文件里的时候,当inject
的值为true
或者body
的时候,所有JavaScript资源将放置在body
元素的下面;当值为head
的时候,将放置在head
元素内。favicon
: 将给定的favicon
路径下的文件输出到html文件里。minify
: 通过使用一个以html-minifier
的配置选项作为内容的对象的时候会压缩输出html文件。使用false
你懂得。hash
: 值为true
|false
。如果为true
的时候添加一个唯一的webpack编写的hash值到所有的script文件和css文件。对于缓存清除很有用。cache
:true
|false
。如果为true
(默认)则只有当文件内容改变的时候,会生成一个新的文件。
showErrors
:true' |
false。如果为
true`(默认),则错误信息写入html页面。chunks
: Allows you to add only some chunks (e.g. only the unit-test chunk)chunksSortMode
: Allows to control how chunks should be sorted before they are included to the html. Allowed values: 'none' | 'auto' | 'dependency' |'manual' | {function} - default: 'auto'excludeChunks
: Allows you to skip some chunks (e.g. don't add the unit-test chunk)xhtml
: true | false If true render the link tags as self-closing, XHTML compliant. Default is false
生成多个HTML文件
如果要生成多个html问卷,只要多声明几次就OK了。
{
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
template: 'src/assets/test.html'
})
]
}
编写自己的模板
如果它默认生成的模板不能满足我们,我们可以自己去编写自己的模板。我们可以通过template
属性传递我们自己的html文件。html-webpack-plugin
将会自动将所有必要的css,js,manifest和favicon文件注入里面。
模板默认使用ejs
模板。如下方式:
plugins: [
new HtmlWebpackPlugin({
title: 'Custom template',
template: 'my-index.ejs', // Load a custom template (ejs by default see the FAQ for details)
})
]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
</body>
</html>
如果你打算使用其他的模板,就需要使用对应的loader进行解析。如下使用了hbs
模板:
module: {
loaders: [
{ test: /\.hbs$/, loader: "handlebars" }
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'Custom template using Handlebars',
template: 'my-index.hbs'
})
]
注意一点就是如果你使用了.html
文件作为模板,那么就会使用html-loader
去解析,所以不要忘记使用html-loader
。(我就卡到这里,不过原因并不是这样。)
注入的对象
在模板中可以使用一下变量:
-
htmlWebpackPlugin
: 这个插件的对象(我理解)htmlWebpackPlugin.files
: webpack的stats对象的assetsByChunkName
表示。它包含输入的文件名到bundle文件名,例如:
"htmlWebpackPlugin": { "files": { "css": [ "main.css" ], "js": [ "assets/head_bundle.js", "assets/main_bundle.js"], "chunks": { "head": { "entry": "assets/head_bundle.js", "css": [ "main.css" ] }, "main": { "entry": "assets/main_bundle.js", "css": [] }, } } }
htmlWebpackPlugin.options
: 转递给插件的options选项,除了插件使用的
选项以外,你可以通过这个hash列表传递任何数据给模板。也就是说你在设置插件选项
的时候,可以添加一些自己的数据。然后可以在模板中通过插件的
options
来使用。 webpack
: webpack的stats对象webpackConfig
webpack的配置对象。
我遇到的坑点
我使用了html
文件作为模板,它需要使用html-loader
进行解析,html-loader
支持es6模板的写法,也就是${}
这样。在写loader的时候,我是这样写的:
module: {
rules: [
{
test: /\.html$/,
loader:'html-loader'
}
]
},
我们模板是酱紫:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>${ htmlWebpackPlugin.options.title }</title>
</head>
<body>
<h1>WMOS</h1>
</body>
</html>
但是这样写之后,它并没有把title
解析掉:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>${ htmlWebpackPlugin.options.title }</title>
<link rel="shortcut icon" href="/dist/favicon.ico"></head>
<body>
<h1>WMOS</h1>
<script type="text/javascript" src="/dist/main.js?6c414fd062ee36677caf"></script></body>
</html>
而将test
那部分改为`test: '/.html$/'的时候,就完美的解析了。
What?我也很懵逼。test的作用是来匹配相应的文件。而test的值可以是字符串,正则,函数等等。看过文档之后,我也并没有发现使用它们会有什么不同的结果。
over day
今天就先写到这里,目前我们遇到了一个奇葩不过不是重点的问题,所以我们先将它记下来,在之后会去一一解决这些问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。