以前初始化
vue
工程都是用的
webapck
的完整配置模板,即:
vue init webpack my-project
最近写一个简单的
vue
组件,准备发布到
npm
,因此决定使用更简洁的
webapck
配置模板,即:
vue init webpack-simple my-project
初始化完成后,发现
index.html
中多了对
build.js
的引用,而
webapck
的完整配置模板中的
index.html
是没有对输出文件
build.js
的引用的,这引起我的注意,决定看看为何有这样的差异。
HtmlWebpackPlugin
最开始我认为完整版的webapck
配置中使用了html-webpack-plugin
插件,该插件会以index.html
为模板,注入引用build.js
的<script src="/dist/build.js"></script>
标签,因此不需要手动在index.html
中引用build.js
。因此我在简洁版webapck
配置中添加了html-webpack-plugin
插件,并删除index.html
中对build.js
的引用,发现并不生效。
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
webpack-dev-server
查阅webpack-dev-server文档,发现有这样的描述:
It will not be written to your configured output directory. Where a bundle already exists at the same URL path, the bundle in memory takes precedence (by default).
大概意思是说,webpack-dev-server
不会把打包出的文件写入硬盘,而是把打包文件保存在内存中,并且优先返回内存中的内容。根据这段描述,我执行npm run dev
启动了服务器(端口8080
),打开http://localhost:8080
,可以正常访问。这时,我的工程中是没有dist
文件夹的,打开http://localhost:8080/dist
也可以正常访问;说明webpack-dev-server
确实在内存中保存着输出文件,在浏览器请求时,webpack-dev-server
返回了内存中的内容。
这下可以理解了,启动服务器后,打开http://localhost:8080
,浏览器会默认去加载根目录下的index.html
,然后再根据<script src="/dist/build.js"></script>
标签去请求build.js
,webpack-dev-server
返回了内存中的build.js
(这个时候,硬盘上并不存在build.js
)。
如果index.html
不引用build.js
,浏览器就不会去请求build.js
,页面不能正常显示。如果不想在index.html
引用打包后的文件(比如每次打包文件名都是随机的),可以使用html-webpack-harddisk-plugin和html-webpack-plugin
使webpack-dev-server
具有向硬盘文件(index.html)注入script
标签的能力,也可以在使用html-webpack-plugin
的前提下将npm run dev
执行的命令修改为:
webpack --config webpack.config.js && webpack-dev-server --open --hot --content-base ./build
即先让webpack
编译再让服务器返回编译结果,事实上vue-cli
的完整版webpack
配置模板就是这样做的。
vue-cli的完整webpack配置模板中的development server实现
根据上面的分析,简洁版webpack配置中必须在index.html
中引用build.js
,页面才能正常显示,但为什么完整webpack
配置模板不需要引入呢。
通过查看完整webpack
配置模板中的./build/dev-server.js
可以看到,其实在完整版中vue-cli
是自己用express
、webpack-dev-middleware
、webpack-hot-middleware
等实现的development server,而不是用的webpack-dev-server
;webpack-dev-middleware
使用webpack
编译源文件并将结果保存在内存中,在浏览器请求资源时,返回内存中的内容;并且该模板中是使用了html-webpack-plugin
的,在编译的时候已经在index.html
中注入了build.js
的引用,因此不需要事先在index.html
写好build.js
的引用。
总结
-
webpack-dev-server
不具备向硬盘文件(index.html)注入script
标签的能力,只能事先在index.html
中写好对build.js
的引用。 -
vue-cli
的完整webpack
配置模板,采用的策略是用webpack-dev-middleware
先编译源文件并保存在内存中(使用html-webpack-plugin
注入js引用),再返回给浏览器。 -
vue-cli
的完整webpack
配置模板是基于express
构建的服务器,没有使用webpack-dev-server
其它
在开发的过程中,我发现vue-cli
的简洁webpack
配置模板在开发模式下,不会把es6
语法转换为es5
语法,而执行打包操作时却会转换。vue-cli
的完整webpack
配置模板不存在这个问题。
在webpack-dev-server
的issues中,有人说,由于是在命令行启动、配置的webpack-dev-server
,webpack
会到全局查找babel
配置,本地的babel
不生效,从而导致语法转换失败。
我个人并没有找到确切原因,望知情人指点。