9
以前初始化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.jswebpack-dev-server返回了内存中的build.js(这个时候,硬盘上并不存在build.js)。
如果index.html不引用build.js,浏览器就不会去请求build.js,页面不能正常显示。如果不想在index.html引用打包后的文件(比如每次打包文件名都是随机的),可以使用html-webpack-harddisk-pluginhtml-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是自己用expresswebpack-dev-middlewarewebpack-hot-middleware等实现的development server,而不是用的webpack-dev-serverwebpack-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-serverwebpack会到全局查找babel配置,本地的babel不生效,从而导致语法转换失败。
我个人并没有找到确切原因,望知情人指点。


whale
649 声望39 粉丝

Enjoy programming