渐进式web运用是大势所趋。越来越多的大公司最先运用这些手艺(比方推特:https://mobile.twitter.com/)。
设想你可以在地铁中浏览一个web运用,这个运用可以向用户推送关照而且供应及时的数据,以及供应类似于app的浏览,这些就是PWA的大抵的才能。
渐进式web运用(PWA)是一个web运用可以供应给用户一种类似于app的体验。PWA得益于当代web科技立异(Service Workers, Native APIS, JS famework)以及提拔的web运用质量标准。
假如你想相识更多关于PWA,请接见这个很棒的Google developer page。
看一下下面的PWA!看起来很像原生的app,是否是?
推特渐进式web运用
从开辟者的角度来看,PWA相关于原生运用具有庞大的长处。它基本上就是一个网站,因而:
你可以挑选任何你喜好的框架来举行开辟;
一段代码搞定统统:它是跨平台的以及跨装备的(代码是经由历程用户的浏览器实行的);
很轻易取得:不须要经由历程运用市肆来下载。
然则,在2017年初期,PWA依旧面对一些限定前提:
Safari不支撑一些基本的PWA特征,比方 Service workers,然则苹果公司好像已预备最先动手了;
一些原生的函数依旧没有获得支撑:关于更多信息,浏览这个页面What web can do。
教程目的
本教程的目的是应用VueJS以及Webpack重新建立一个基本的然则完全的渐进式web运用。我们的运用将会满足引见内里的一切需求:渐进式的,相应式的,衔接自力的等等。我想给你一个可以在PWA内完成的目的的总览:流通的原生式的运用,离线行动,原生特征构造,推送关照。
为了让事变坚持挑战性,我们盘算构建一个猫图信息app:CropChat!CropChat用户可以浏览主流的猫的图片,而且可以翻开他们相识更多细节以及上传新的猫的图片(首先从互联网,接着是从装备驱动或许照相机)。
这个教程将会分为几个部份,它们将会一连地举行宣布
[Part 1] Lite基于Vue JS, Webpack 以及Material Design的渐进式web运用
[Part 2] 基于Vue-Resource以及VueFire将App和长途的API举行衔接
[Part 3] 基于Service Worker来完成离线形式
[Part 4] 接见装备照相机来照相
[Part 5] 接见装备驱动来上传图片
[Part 6] 完成推送关照
[Part 7] 接见装备地点
我们的PWA的基本组件
我们的渐进式web运用是基于你喜好的如今组件!
VueJS 2视图层: 经由历程应用Material Design Lite来衬着视图
Vue-Router:处置惩罚SPA路由
Vue-Resource & Vuefire: 处置惩罚和Firebase数据库的通讯
Service Worker:处置惩罚离线形式而且坚持数据更新
Webpack & Vue-loader:构建我们的运用,供应热加载 build our application, provides hot reload, ES2016 and pre-processors.
让我们最先part 1!
[PART 1] Lite基于VueJS, Webpack 以及 Material Design Lite建立一个单页面运用
假如你不熟悉VueJS 2,我强烈建议你浏览官方教程。
构建VueJS APP基本
我们盘算应用Vue-cli来建立我们的运用:
`npm install -g vue-cli`
Vue-cli自带一些模板。我们将会挑选webpack模板。Webpack是一个关于Javascript运用的当代模块打包东西,它可以处置惩罚而且构建我们的资本。Vue-cli将运用Webpack,vue-loader(热加载!),JS linter以及测试套件来建立一个假造的VueJS运用。
`vue init webpack cropchat`
你能够会问一些问题。下面是我运用过的设置:
`This will install Vue 2.x version of the template.`
`For Vue 1.x use: vue init webpack#1.0 cropchat`
? Project name cropchat
? Project description Image messenging application
? Author Charles BOCHET <charlesb@theodo.fr>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? Yes
? Setup e2e tests with Nightwatch? No
`vue-cli · Generated "cropchat".`
这个历程会建立一个包括以下子文件夹的项目文件夹:
build: 包括webpack以及vue-loader设置文件
config: 包括我们的app设置(环境,参数等等)
src: 我们运用的源代码
static: 图片,css以及别的的公共资本
test: Karma & Mocha建立的单元测试文件
然后运转:
cd cropchat
npm install
npm run dev
这将会在你的浏览器翻开localhost:8080
:
经由历程一个适宜的Manifest让它可以举行装置:
PWA的最大长处之一就是轻易装置而且分享。让我们别再等待了!
为了如许做,我们须要增加一个manifest.json文件而且在index.html文件中举行声明。
pwa-manifest-webpack-plugin
可以让我们在运用构建的时刻天生文件:
`npm i pwa-manifest-webpack-plugin --save`
我们接着可以经由历程编辑build/webpack.dev.conf.js
以及build/webpack.prod.conf.js
来更新构建历程。
在顶部引入pwa-manifest-webpack-plugin
:
var path = require('path')
var manifestPlugin = require('pwa-manifest-webpack-plugin')
而且将它增加到插件:
plugins: [
new manifestPlugin({
name: 'CropChat',
description: 'CropChat - Image Messenger Application',
display: 'fullscreen',
icon: {
src: path.resolve('src/assets/logo.png'),
sizes: [200]
}
}),
末了,在 index.html
中声明运用manifest.json
:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="manifest" href="./manifest.json">
你能够须要重启你的运用:来如许做,杀掉之间的历程而且再次运转:
`npm run dev`
就是它了!让我们在手机装备上装置CropChat。有多种体式格局可以从差别的手机装备上接见localhost:8080
。我最喜好就是运用ngrok。
Ngrok是一种效劳,可以长途登录您的当地环境,免费!
装置它:
`npm install -G ngrok`
接着,运转:
`ngrok http 8080`
那应当会给你以下的输出:
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Version 2.1.18
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://5ef29506.ngrok.io -> localhost:8080
Forwarding https://5ef29506.ngrok.io -> localhost:8080
Connections ttl opn rt1 rt5 p50 p90
39 3 0.01 0.01 120.01 881.89
经由历程你的手机浏览ngrok的url http://5ef29506.ngrok.io
。你可以在你的装备桌面增加!
Cropchat的源代码可以在GitHub here上可以接见。Git汗青相符教程的步骤:你可以鄙人面的commit 5ff77fd3cd71a988fad9c187d57e87ea80d670f0种发明这个步骤的变化
想相识更多关于ngrok,你可以浏览Matthieu Auger的文章:Expose your local environment to the world with ngrok
建立视图框架和句柄路由
既然我们已具有适宜的基本,那末我们盘算最先构建CropChat的特征。CropChat具有三个视图:
Home View: 展现一个猫的图片列表
Detail View: 展现特定猫的图片的细节(在Home View种点击接见)
Post View: 可以让用户上传一个新的图片
建立一个具有以下框架的src/component/HomeView.vue
视图:
<template>
<ul class="list">
</ul>
</template>
<script>
export default {
}
</script>
<style scoped>
.list {
width: 100%;
padding: 0;
}
</style>
关于src/component/DetailView.vue
视图也是一样的:
<template>
<div class="card-image">
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
关于 src/component/PostView.vue
也是一样的:
<template>
<div class="waiting">
Not yet available
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.waiting {
padding: 10px;
color: #555;
}
</style>
终究,更新路由文件 src/router/index.js
:
import Vue from 'vue'
import Router from 'vue-router'
import HomeView from 'components/HomeView'
import DetailView from 'components/DetailView'
import PostView from 'components/PostView'
`Vue.use(Router)`
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/detail/:id',
name: 'detail',
component: DetailView
},
{
path: '/post',
name: 'post',
component: PostView
}
]
})
也移除没有运用的Hello.vue视图。你应当你可以直接看到影响你手机app的变化(热加载很棒,是否是?)
Git commit: 22ab9a2058dae8f7689b8635ff52d89652675aa6
装置 Material Design Lite
不知道Material Design Lite?它是一个轻量级的而且轻易在你的web运用上完成Material Design 的框架。
你可以在这看到更多的文档:Get MDL.io
更新依靠:
`npm install material-design-lite --save`
更新src/App.vue
来导入MDL款式而且加载MDL模块:
<script>
require('material-design-lite')
...
</script>
<style>
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://code.getmdl.io/1.2.1/material.blue-red.min.css');
</style>
Git commit: b726b40488132c400dd861bd397f61b15e81631e
为你的单页面运用供应一个导航栏:
更新重要组件src/App.vue
种的模块部份:
<template>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<header class="mdl-layout__header">
<div class="mdl-layout__header-row">
<span class="mdl-layout-title">CropChat</span>
</div>
</header>
<div class="mdl-layout__drawer">
<span class="mdl-layout-title">CropChat</span>
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="/#/" @click="hideMenu">Home</a>
<a class="mdl-navigation__link" href="/#/post" @click="hideMenu">Post a picture</a>
</nav>
</div>
<main class="mdl-layout__content">
<div class="page-content">
<router-view></router-view>
</div>
</main>
</div>
</template>
由于Material Design Lite不是特别为单页面运用构建的,因而在用户点击菜单链接的时刻我们须要隐蔽burger菜单:
<script>
...
export default {
name: 'app',
methods: {
hideMenu: function () {
document.getElementsByClassName('mdl-layout__drawer')[0].classList.remove('is-visible')
document.getElementsByClassName('mdl-layout__obfuscator')[0].classList.remove('is-visible')
}
}
}
</script>
Git commit: 829d0af767a9f7cba13355296d9da79384d80099
流传视图并将你的运用带到生涯
我们还没有衔接一个背景的效劳。我们如今盘算临时运用假数据。
建立一个src/data.js
文件:
export default {
pictures: [
{
'id': 0,
'url': 'http://25.media.tumblr.com/tumblr_m40h4ksiUa1qbyxr0o1_400.gif',
'comment': 'A cat game',
'info': 'Posted by Kevin on Friday'
},
{
'id': 1,
'url': 'http://25.media.tumblr.com/tumblr_lhd7n9Qec01qgnva2o1_500.jpg',
'comment': 'Tatoo & cat',
'info': 'Posted by Charles on Tuesday'
},
{
'id': 2,
'url': 'http://24.media.tumblr.com/tumblr_m4j2atctRm1qejbiro1_1280.jpg',
'comment': 'Santa cat',
'info': 'Posted by Richard on Monday'
},
{
'id': 3,
'url': 'http://25.media.tumblr.com/tumblr_m3rmbwhVB51qhwmnpo1_1280.jpg',
'comment': 'Mexico cat',
'info': 'Posted by Richard on Monday'
},
{
'id': 4,
'url': 'http://24.media.tumblr.com/tumblr_mceknxs4Lo1qd477zo1_500.jpg',
'comment': 'Curious cat',
'info': 'Posted by Richard on Monday'
}
]
}
在HomeView.vue
script部份中导入数据而且将图片链接到对应的细节视图:
<script>
import data from '../data'
export default {
methods: {
displayDetails (id) {
this.$router.push({ name: 'detail', params: { id: id }})
}
},
data () {
return {
'pictures': data.pictures
}
}
}
</script>
更新HomeView.vue
模板和款式:
<template>
<div>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--3-col mdl-cell mdl-cell--1-col-tablet mdl-cell--hide-phone"></div>
<div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-phone">
<div v-for="picture in this.$data.pictures" class="image-card" @click="displayDetails(picture.id)">
<div class="image-card__picture">
<img :src="picture.url" />
</div>
<div class="image-card__comment mdl-card__actions">
<span>{{ picture.comment }}</span>
</div>
</div>
</div>
</div>
<a class="add-picture-button mdl-button mdl-js-button mdl-button--fab mdl-button--colored" href="/#/post">
<i class="material-icons">add</i>
</a>
</div>
</template>
...
<style scoped>
.add-picture-button {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 998;
}
.image-card {
position: relative;
margin-bottom: 8px;
}
.image-card__picture > img {
width:100%;
}
.image-card__comment {
position: absolute;
bottom: 0;
height: 52px;
padding: 16px;
text-align: right;
background: rgba(0, 0, 0, 0.5);
}
.image-card__comment > span {
color: #fff;
font-size: 14px;
font-weight: bold;
}
</style>
对DetailView.vue
举行一样的操纵:
<template>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--8-col">
<div class="picture">
<img :src="this.$data.pictures[$route.params.id].url" />
</div>
<div class="info">
<span>{{ this.$data.pictures[$route.params.id].info }}</span>
</div>
</div>
<div class="mdl-cell mdl-cell--4-col mdl-cell--8-col-tablet">
<div class="comment">
<span>{{ this.$data.pictures[$route.params.id].comment }}</span>
</div>
<div class="actions">
<a class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" href="/#/post">
ANSWER
</a>
</div>
</div>
</div>
</template>
<script>
import data from '../data'
export default {
data () {
return {
'pictures': data.pictures
}
}
}
</script>
<style scoped>
.picture > img {
color: #fff;
width:100%;
}
.info {
text-align: right;
padding: 5px;
color: #555;
font-size: 10px;
}
.comment {
padding: 10px;
color: #555;
}
.actions {
text-align: center;
}
</style>
Git commit: 39360f251da153c780cd148dc3cf234348bb1e87
关于’href’链接的运用:我引荐运用vuejs的组件然则在这我想使代码尽量的简朴。
末了的效果
我们完成了,CropChat完成啦!
源代码可以在GitHub repository接见: https://github.com/charlesBochet/vueJSPwa
总结
我愿望我已令你确信你可以应用VueJS和Webpack就可以简朴地建立web运用。总结来讲:
Vue-cli可以在命令行种建立一个假造的VueJS + Webpack运用
经由历程增加Manifest.json文件让你的web运用可以装置
运用Vue-Router以及Material Design来建立一个类似于app用户体验的运用
然则,CropChat还依旧不是一个渐进式web运用:让我们看一下PWA的需求清单:
一半的需求还没有满足。鄙人一个部份将会有别的的目的。未完待续!
译者注:
安利几个我之前翻译过的别的的关于PWA的文章以及我本身的PWA小运用: