使用webpack提升vue应用的4种方式

时间: 2017-11-27阅读: 1141标签: vue
译者注:本篇文章所提到的几个措施大家可能都曾经在项目里用过,但是就如作者所言:你只是在用,并不知道为什么用,本文最大的价值在于提供了系统的优化方案并解释了原因

webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:

单文件组件
优化Vue构建过程
浏览器缓存管理
代码分离


关于vue-cli

如果你在使用 vue-cli 提供的模板来构建你的应用,那么webpack的相关配置已经提供好了,这些配置已经经过很好地优化,我也给不了你其他的优化建议了。

不过因为配置是开箱即用的,所以你很有可能并不知道这些配置真正在做什么,由于 vue-cli 里提供了我将要讨论的优化措施,所以,你可以把这篇文章当做模板里webpack配置的概述。

1.单文件组件

Vue的特点之一就是使用了基于HTML的模板组件,这带来了一个本质问题:要么HTML标记使用丑陋的Java字符串,要么将模板内容和组件定义写在不同的文件中。这带来了一些困难。

Vue提供了一种叫做Single File Components(SFCs)的方式来解决这个问题,将模板、组件定义、CSS写在一个 .vue 文件里。

MyComponent.vue

<template>
<div id="my-component">...</div>
</template>
<>
exportdefault{...}
</>
<style>
#my-component {...}
</style>


Vue-loader 使得 SFCs成为可能,这个 webpack loader 将SFCs分隔成不同语言块,然后输出到合适的loader,例如 块 输出到babel-loader, 模板块输出到Vue自己的vue-template-loader,该loader能够将模板转换成Java的render函数。

vue-loader的最终输出是一个将要包含在 Webpack bundle 中的Java模块。

典型的vue-loader配置如下所示:

module:{
rules:[
{
test:/.vue$/,
loader:'vue-loader',
options:{
loaders:{
// Override the default loaders
}
}
},
]
}


2.优化Vue构建

运行时构建

如果在你的应用中仅仅使用 render函数,不需要HTML模板,那你不需要使用Vue的模板编译器,通过去掉模板编译器,可以让你在Webpack构建过程中,减少bundle 的体积。

记住单文件组件在开发模式中使用了预编译

Vue的运行时构建版本包含了Vue的所有特点,除了模板编译器,被称为vue.runtime.js,体积比全功能版本小了20KB,所以这值得你尝试一下。

默认情况下使用的是运行时构建版本,所以当你使用 import vue from 'vue' 来引用Vue的时候,你得到的是运行时构建版本,不过你能通过 alias 配置项来改变。

resolve:{
 alias:{
  'vue$':'vue/dist/vue.esm.js'// Use the full build
 }
}


译者注:在Vue模块中包含8个文件,各文件的区别可以参考:官方文档,在需要使用完整版时使用了运行时版本会报warn:

You are using the runtime-only build of Vue where the template option is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

production环境中去掉 warn 和 error 信息

另外一个减少Vue构建体积的方式是在 production环境中去掉所有 error 和 warn信息,这些不必要的代码导致你打包后的体积膨胀,而且增加了运行时耗时,你最好避免这些消耗。

如果你调试Vue的源代码,你会发现这些提示信息都是通过环境变量 process.env.NODE_ENV 的值来判断的,例如:

if(process.env.NODE_ENV !=='production'){
 warn(("Error in "+info +": ""+(err.toString())+"""),vm);
}


如果 process.env.NODE_ENV 的值设置成 production ,那么提示信息在构架过程中就会自动被剔出去。

可以通过使用 DefinePlugin 去设置 process.env.NODE_ENV 的值,同时使用 UglifyJsPlugin 去减小代码体积并且去掉不需要的代码块。

if(process.env.NODE_ENV ==='production'){
module.exports.plugins =(module.exports.plugins ||[]).concat([
newwebpack.DefinePlugin({
'process.env':{
NODE_ENV:'"production"'
}
}),
newwebpack.optimize.UglifyJsPlugin()
])
}


译者注:实际项目中使用的更多的方式是 production环境 和 其他环境 使用不同的webpack配置文件.

3.浏览器缓存管理

浏览器能够缓存你的站点文件,只有在你本地没有副本时或者副本已经过期时才会重新下载。

如果你所有的代码都在一个文件里,那一个微小的改动也会导致整个文件的下载,理想情况下,你想要你的用户尽可能少的下载文件,所以将频繁改动的代码和不怎么改动的代码分开是非常明智的。

Vendor file

Common Chunks插件能把你的Vendor代码(例如Vue.js这些不会经常改动的依赖包)和应用代码(每次开发过程中都会改动的代码)分离开。

你能配置插件检查一个依赖是否来自于node_modules,如果是,那就打包到vendor.js 文件。

newwebpack.optimize.CommonsChunkPlugin({
name:'vendor',
minChunks:function(module){
returnmodule.context &&module.context.indexOf('node_modules')!==-1;
}
})


这么做之后,在构建后的输出文件中,将有两个独立的文件,能够分别被浏览器缓存。

< src="vendor.js"charset="utf-8"></>
< src="app.js"charset="utf-8"></>


指纹

当构建后的文件改动了,我们该怎么丢弃缓存呢?

默认情况下,只有当一个缓存文件过期,或者用户手动清除缓存,浏览器才会重新从服务器请求文件,如果服务器提示文件已经改动,那文件才会重新被下载(如果返回304则不会)。

为了避免不必要的请求,我们可以在每次文件内容改动时,改变文件的名字,从而强制浏览器重新下载,通过在文件名称后面添加一个"指纹":hash,我们可以非常容易达到这个目的。


Common Chunks插件生成"chunkhash",能随着文件的改动而更新,Webpack能在输出时,将这个hash值添加到文件名称末尾。

output:{
filename:'[name].[chunkhash].js'
},


这样做的话,你会发现输出的文件名称类似于app.3b80b7c17398c31e4705.js。

译者注:chunkhash并不需要Common Chunks生成,而是webpack自动生成的,而且据官方文档,Common Chunks是无法生成chunkhash的,作者在这里这么写让我摸不着头脑, 另外,还有一种添加hash值的方式是使用

output:{
filename:'[name].[hash].js'
},


其中的区别主要在于chunkhash是基于内容生成的hash值,而hash值是基于模块标识(webpack打包时每个模块都有一个唯一标识),hash值的主要问题在于任何一个文件更新之后都会更新hash值,导致那些内容没有更新的文件的文件名也更新了,需要重新下载。具体区别可参考:webpack配置:缓存。

自动插入构建文件

当然了,增加了hash值之后,你就必须要在index文件里更新你的引用,否则浏览器是不会知道的。

< src="app.3b80b7c17398c31e4705.js"></>


手动去做这件事将是一件非常沉闷无聊的事情,可以使用HTML Webpack Plugin来做这件事。这个插件能在构建过程中自动在你的HTML文件里插入对构建文件的引用。

先来把构建文件中的引用去掉

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test-6</title>
</head>
<body>
<div id="app"></div>
<!--built files should go here,but will be auto injected -->
</body>
</html>


然后在Webpack配置里增加HTML Webpack Plugin 的配置。

newHtmlWebpackPlugin({
filename:'index.html'
template:'index.html',
inject:true,
chunksSortMode:'dependency'
})


现在带有hash值的构建文件将会自动增加到index文件,同时,你的index.html文件也会被包含在输出文件里,所以你可能需要将这一点告诉服务器。

4.代码分离

默认情况下,Webpack将把你的所有应用代码输出到一个大的构建文件中,但是如果你有多个页面,分隔代码将每个独立的页面输出到不同的文件中,只有在需要的时候才去加载。

Webpack有个功能 "code splitting",可以用来做这件事,在Vue.js中需要使用async components,配合Vue Router使用更简单。

Async componets

相比以一个定义对象作为第二个参数,Async components第二个参数是一个Promise函数,该函数将一个对象resolve,例如:

Vue.component('async-component',function(resolve,reject){
setTimeout(()=>{
resolve({
// Component definition including props, methods etc.
});
},1000)
})


Vue只有在这个组件需要被渲染时,才会调用这个函数,同时也会为以后的预渲染缓存返回结果。

如果我们将每个页面都当做一个组件,并且将定义对象放在服务器端,那在代码分离的路上,我们已经走了一半了。

require

为了从服务器上加载你的异步组件代码。使用Webpack的require语法,这将通知Webpack将async-component打包到一个分隔的bundle,更妙的是,Webpack将使用AJAX处理bundle的加载,所以你的代码可以像下面这样简单:

Vue.component('async-component',function(resolve){
require(['./AsyncComponent.vue'],resolve)
});


懒加载

在Vue.js应用中,vue-router是一个典型模块,你可以用它来将SPA转换成多页应用,懒加载是利用Vue和Webpack实现代码分离的官方推荐方式。

constHomePage =resolve =>require(['./HomePage.vue'],resolve);
constrounter =newVueRouter({
routes:[
{
path:'/',
name:'HomePage',
component:HomePage
}
]
})


关于本文

译者:@孙辉
作者:@ANTHONY GORE
原文:http://vuejsdevelopers.com/2017/06/18/vue-js-boost-your-app-with-webpack


站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/174

Vue 的 .sync 修饰符

.sync 修饰符算是 Vue 的所有修饰符中较难理解的一个,本篇文章就带你走近 .sync 的世界,深入理解后会发现,其实也就那么回事。修饰符和指令息息相关,下面从 指令 -> 修饰符 -> .sync 修饰符 由浅入深地来讲解 .sync 的含义及用法。

vue中is的作用和用法

总所周知,ul里面嵌套li的写法是html语法的固定写法(还有如table,select等)。my-component是我们自己写的组件,但是html在渲染dom的时候,my-component对ul来说并不是有效的dom,甚至会报错。

一点 Vue.observable 想法

Vue 2.6.0 新增了 Vue.observable api,但最近才去尝试使用它。这东西说新也不新,因为他就是 vue 本身的功能,只是暴露出来,成为新 api 了。在老版本中,直接用 new Vue({ data: {} }) 也一样。

Vue中props知识点

如果你一直在阅读有关\\\"props\\\"内容,你会发现我们可能也一直在使用它们(即使没有意识到),但也许你并不完全确定它们是什么。或者如何正确使用它们,并充分利用它们。

12种使用Vue的最佳做法

随着 VueJS 的使用越来越广泛,出现了几种最佳实践并逐渐成为标准。在本文中,主要分享在平时开发中一些有用资源和技巧,废话少说,我们开始吧。

如何理解vue中的v-bind?

若不是动态属性,首先为其增加驼峰化后的监听,然后再为其增加一个连字符的监听,例如v-bind:foo-bar.sync,首先v-on:update:fooBar,然后v-on:update:foo-bar。v-on监听是通过addHandler加上的。

Vue.use到底是什么?

我们在使用Vue做项目开发的时候,看到不少轮子都是通过Vue.use来进行使用,感觉甚是高大上。不过Vue.use到底是什么鬼?不妨来看个究竟。

Vue.js最佳实践:五招让你成为Vue.js大师

本文面向对象是有一定Vue.js编程经验的开发者。如果有人需要Vue.js入门系列的文章可以在评论区告诉我,有空就给你们写。对大部分人来说,掌握Vue.js基本的几个API后就已经能够正常地开发前端网站

vue介绍

库是一种插件,是一种封装好的特定方法的集合。提供给开发者使用,控制器在使用者手里。框架是一套架构,会基于自身特定向用户提供一套相当完整的解决方案,控制权在框架本身

vue有时候你不需要 $emit & $on

在此之前,子组件到父组件的传递事件我一般还是使用 $emit 和 $on,因为这个操作理解起来并不难,代码一般也挺清晰。不过今天遇到这么个情况 ——

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广