基于Vue JS, Webpack 以及Material Design的渐进式web应用第1部分

Posted 奇舞周刊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Vue JS, Webpack 以及Material Design的渐进式web应用第1部分相关的知识,希望对你有一定的参考价值。


(图片来自网络)

编者按:本文由neal1991在众成翻译平台上翻译。建议同学们动手试试本文的内容~

渐进式Web应用是大势所趋。越来越多的大公司开始使用这些技术(比如Twitter:https://mobile.twitter.com/)。

想象当你在地铁中浏览一个Web应用的时候,这个应用通过推送通知、提供实时数据、以及提供类似于APP的导航,让你沉浸其中。这些就是PWA的神奇所在。

渐进式Web应用(PWA)是一种能够提供给用户类似于APP的体验的Web应用。PWA得益于现代Web科技的创新(Service Workers,  Native APIS,  JS famework),它可以提升的Web应用的质量标准。

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

如果你想了解更多关于PWA的信息,请访问这个很棒的网站Google developer page

看一下下面的PWA!看起来很像原生的APP,是不是?

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

Twitter渐进式Web应用

从开发者的角度来看,PWA相比于原生应用拥有巨大的优点。它基本上就是一个网站,因此:

  • 你可以选择任何你喜欢的框架来进行开发;

  • 一段代码搞定一切:它可以跨平台、跨设备(代码是通过用户的浏览器执行的);

  • 易于传播:不需要通过应用商店来下载。

然而,在2017年早期,PWA仍然面临一些限制条件:

  • Safari不支持一些基本的PWA特性,比如 Service worker,但是苹果公司似乎已经准备开始着手处理了;

  • 一些原生的函数依然没有得到支持:可以浏览这个页面What web can do 获得更多信息。

教程目标

本教程的目标是利用VueJS以及Webpack从头创建一个基础但完整的渐进式Web应用。我们的应用将会满足介绍里面的所有需求:渐进式的,响应式的,连接独立的等等。我想大致让你看看PWA能够实现些什么:流畅的类原生应用,离线行为,原生特性接口,推送通知。

为了让事情有些挑战性,我们打算构建一个猫咪图片交流app:CropChat!CropChat用户能够浏览猫咪照片流,点击图片之后可以打开这个猫咪的详情介绍,用户也可以发布新的猫咪图片(图片资源可以是来自互联网,来自设备图片库或通过照相机拍摄的)。

这个教程将会分为几个部分:

  • [Part 1]  创建一个基于VueJS, Webpack 以及Material Design Lite的单页面应用

  • [Part 2] 基于Vue-Resource以及VueFire将App和远程的API进行连接

  • [Part 3] 利用Service Worker来实现离线模式

  • [Part 4] 访问设备照相机进行拍照

  • [Part 5] 访问设备驱动上传图片

  • [Part 6] 实现推送通知

我们的PWA的基本组件

我们的渐进式Web应用是基于你喜欢的现代组件!

  • VueJS 2视图层: 利用Material Design Lite来渲染视图

  • Vue-Router:处理单页应用的路由

  • Vue-Resource & Vuefire:  处理和Firebase数据库的通信

  • Service Worker:处理离线模式并且保持数据更新

  • Webpack & Vue-loader:构建我们的应用,提供热加载、ES2016 和 预处理器。

让我们开始第一部分吧!

[第1部分] 创建一个基于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

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

通过添加一个合适的Manifest让它可以进行安装:

PWA的最大优点之一就是容易安装并且分享,下面我们就开始着手做吧!

为了这样做,我们需要添加一个manifest.json文件并且在index.html文件中进行声明。

pwa-manifest-webpack-plugin 这个包支持应用构建的时候生成这个文件:

`npm i pwa-manifest-webpack-plugin --save`

接着我们通过编辑build/webpack.dev.conf.jsbuild/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是一种支持远程登录您的本地环境的免费服务。

安装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

使用你的手机访问 http://5ef29506.ngrok.io ,你就能够在你的手机桌面上添加CropChat这个APP了。

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

Cropchat的源代码能够在GitHub here上看到。这个教程中的每一个部分都能够在Git的历史记录里找到: 5ff77fd3cd71a988fad9c187d57e87ea80d670f0 这个commit就是教程的第一部分。

想了解更多关于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

更新CropChat的依赖:

`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">

        <class="mdl-navigation__link" href="/#/" @click="hideMenu">Home</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>

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

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>

    <class="add-picture-button mdl-button mdl-js-button mdl-button--fab mdl-button--colored" href="/#/post">

      <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">

        <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完成啦!

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

基于Vue JS, Webpack 以及Material Design的渐进式web应用【第1部分】

源码放在了这个 GitHub 仓库里: https://github.com/charlesBochet/vueJSPwa

总结

我相信通过这个教程你已经有能力能够很轻松地使用VueJS和Webpack来创建一个web应用,总结一下:

  • Vue-cli用过仅仅一行命令来创建一个VueJS + Webpack应用

  • 通过添加Manifest.json文件让你的web应用能够安装

  • 使用Vue-Router以及Material Design来创建一个类app用户体验的应用

然而,CropChat 还依然不是一个渐进式 Web 应用:让我们看一下PWA的需求清单:

啊,还有一半的目标没有实现!那么在接下来的几部分中,我们将完成这些目标,敬请期待!


奇舞周刊

——————————————————

领略前端技术 阅读奇舞周刊


长按二维码,关注奇舞周刊


以上是关于基于Vue JS, Webpack 以及Material Design的渐进式web应用第1部分的主要内容,如果未能解决你的问题,请参考以下文章

npm webpack vue-cli

npm webpack vue-cli

基于webpack的Vue.js开发环境快速搭建

基于webpack搭建cesium+vue应用

[js高手之路]Vue2.0基于vue-cli+webpack父子组件通信教程

Vue.js——60分钟webpack项目模板快速入门