Recently, in the spare time of autumn recruitment, I have made a project based on my own interests, which is an experiment of browsing mobile webApp based on Vue, typescript and PWA. Now I am taking advantage of the hot iron to record the whole process of the project from development to deployment, and share what I have learned from the project. If you have any comments or additions, please feel free to post them in the comments section. Let me introduce you to the project

Project introduction

BrowseExp is a mobile webapp based on Vue, typescript, AND PWA. Its main function is to browse some experimental information of school psychology. (Above is a level 1 entry added to the desktop). Now that the project has been deployed to the server, let’s take a look at what the final project looks like running on the client side



As you can see, I entered our WebApp through a level 1 portal on the desktop, and I did it with no network connection. That’s where THE PWA comes in, and I’m going to share the development-to-deployment process.

Why did you do this project?

  1. Pwa has been popular in China for some time, but I have not made a PWA app myself.
  2. Vue-cli 3.0 added support for PWA
  3. Support for TS has been added since VUe2.5
  4. Trying to mess things up!

The development process

The project’s address is browseExp pwa, so if you want to look at the code, look it up. The main points to note in this project are:

  • Use TS in VUE
  • Simple skeleton screen application
  • First screen load time and SEO optimization
  • Implementation of PWA related features
  • Mobile side of some issues resolved
  • How to deploy the project

The rest of the content will also revolve around these points.

Ts is used in VUE

The main reason for using TS is that it gives us a type system that allows us to write robust code. It’s particularly useful in large projects, so it’s highly encouraged. We use TS for development, usually writing class-based VUE components. So you can use the officially maintained Vue-class-Component or vue-property-decorator. Vue-cli3.0 also provides typescript support out of the box, and the development experience is fairly friendly. A vUE component demo:

import { Component, Vue, Prop } from 'vue-property-decorator'; @Component export default class Name extends Vue { @Prop() private name! : string; private complete! : boolean; private data() { return { complete: false, }; } private myMethod() { // ... } private created() { // ... }}Copy the code

In addition, under the scaffolding provided by VUe-CLI3.0, it is possible to add global interfaces or variables, etc., under the shims-TSx.d. ts file to define type declarations for third-party packages under the Shims-vue.d. ts file.

Simple use of skeleton screen

Skeleton screen is no longer a novel concept. Its main function is to transition the blank state of a page and improve user experience, such as page jump wait and data load wait. Traditional skeleton screen implementation schemes include server-side rendering and pre-rendering, etc. The purpose of the skeleton screen in this project is to get over the partial blank state of the page when the data is loaded, so we wrote a skeleton screen component to make the transition.






If you have a bigger need for a skeleton screen, you can find more tutorials online, which are not listed here.

First screen loading speed and SEO optimization

One drawback of single Page Web Application (SPA) is that it requires a lot of content to load the first time, so the first screen load time is long. In addition, the single-page application is not conducive to the search engine because the data is front-loaded to the front end. So we need to optimize our one-page app. We used the prerender-spa-plugin, a Webpack plugin that prerenders the route we specified to HTML to solve the problem of a long white screen for the first load and to some extent solve the SEO problem. In VUe-Cli3.0, our configuration is hidden and we can merge our configuration into the default configuration via vue.config.js.

// vue.config.js const path = require('path') const PrerenderSPAPlugin = require('prerender-spa-plugin') module.exports = { configureWebpack(config) { if (process.env.NODE\_ENV ! == 'production') return; return { plugins: \[ new PrerenderSPAPlugin({ // Required - The path to the webpack-outputted app to prerender. staticDir: path.join(\_\_dirname, 'dist'), // Required - Routes to render. routes: \['/'\], }) \] } }, }Copy the code

Effect:



The above picture shows the effect of this app when it is opened for the first time in slow 3G network environment. You can see the whole process. We jump from Google page to browseExp first, and the first thing we see is our pre-rendered page, which replaces the white screen loading time of the app after MY URL jump. After loading, it will request our data. At this time, the skeleton screen will appear, and the partial blank screen time of this page will finally become the real page. Pre-rendering also has its drawbacks: the pre-rendered page content may be different from the real thing, and it is not interactive. Therefore, if the content of the application has a strong real-time and interactive, you can consider using the skeleton screen to carry out the white screen transition of the first screen loading, but this will not be able to optimize SEO, so choose according to your actual scene.

Upgrade the project to PWA

Once our project is basically in shape, we can consider upgrading it to PWA. I’m sure you all know what PWA is. It’s been popular abroad for hundreds of years, but not many people in China have tried it, except for a few big companies. But last year, PWA became popular in China. Pwa is our product in the process of pursuing the combination of convenience of WebApp and good experience of native application. At present, compatibility is the biggest obstacle, but I believe it has a bright prospect in China. Pwa features offline, add to desktop (level 1 entry), background synchronization, server push, etc. This project has realized offline and add to desktop these two functions. When I first heard about PWA, I thought it would be very complicated, but after practice, I found it was very simple.

Ps: The development process can be debugged in the Application of the console




workbox

Workbox is a collection of pWA tools around which there are a number of other tools such as workbox-cli, gulp-workbox, workbox-webpack-plagin, etc. Workbox itself is equivalent to a framework for service workers. It encapsulates various apis and cache strategies, making it easier for us to use service workers. Vue-cli3.0 integrates workbox-webpack-plagin, which we can configure via the vue.config.js pWA configuration item first, in the vue.config.js file, more detailed configuration item

Module. Exports = {myController-exp ', themeColor: '#6476DB', msTileColor: '#000000', appleMobileWebAppCapable: 'yes', appleMobileWebAppStatusBarStyle: 'black', /\* \* GenerateSW (default) and InjectManifest \* GenerateSW when we build the project, InjectManifest allows you to edit a custom service worker file for more functionality and get a cached list of workboxPluginMode: 'InjectManifest', workboxOptions: {// Custom service worker file location swSrc: 'SRC /service-worker.js', //... other Workbox options... }}Copy the code

We need to create a new service-worker.js file under the SRC directory.

  • Workbox. Precaching Caches static support
  • Workbox. routing Indicates route control
  • Workbox. Strategies provides caching strategies
  • , etc.

More detailed interface and configuration tutorials

/ / SRC/service - worker. Js / / set the corresponding cache name prefixes and suffixes workbox. Core. SetCacheNameDetails ({prefix: 'browse - exp, suffix: 'v1.0.0}); // Let our service worker get updated as soon as possible and get control of the page workbox.skipwaiting (); workbox.clientsClaim(); /\* \* vue-cli3.0 uses workbox-webpack-plagin to obtain the pre-cached list and pre-cache them, i.e. the HTML, js produced after the packaged project, CSS and other static files \ \ * * / workbox. Precaching. PrecacheAndRoute (self. \ _ \ _precacheManifest | | \ [\]); / / data caching to our request, here adopt the strategy of networkFirst workbox. Routing. RegisterRoute (new RegExp ('. \ * experiments? .\*'), workbox.strategies.networkFirst() ); workbox.routing.registerRoute( new RegExp('.\*experiments/\\d'), workbox.strategies.networkFirst() ) workbox.routing.registerRoute( new RegExp('.\*experiment\_types.\*'), workbox.strategies.networkFirst() )Copy the code

Here, the first by workbox. Precaching. PrecacheAndRoute app shell configuration cache, and then through workbox. Routing. RegisterRoute to request data cache, Because the requested data has a certain real-time requirement, so the networkFirst policy is adopted. Here are some related policies:

networkFirst

Network priority policy: It tries to obtain data through network request first, returns the data to the user after obtaining the data, and updates the cache. If the data fails to obtain, the data in the cache will be used.

cacheFirst

The cache priority policy is to obtain the resources in the cache first. If there are no relevant resources in the cache, the network request is initiated.

networkOnly

As the name implies, only resources obtained by network requests are used

cacheOnly

As the name implies, only resources in the cache are used

stateWhileRevalidate

This policy directly returns the resource in the cache, ensures that the resource is retrieved quickly, and then initiates a network request to retrieve data to update the resource in the cache. If there is no corresponding resource in the cache, the network request is made and the resource is cached.

How do you see the effect

These configurations allow us to run offline, but they are relative to the packaged project file, the dist file. We don’t experience the effects in dev mode during development. How do we see the effects?

  • Plan 1: To write a background service, we can write a background service through Node. js to access our application. The service worker originally needs to run in THE HTTPS environment, but if it is in the local localhost environment, the service worker can run on the HTTP protocol.
  • Option 2: Use the Chrome extension application Web Server for Chrome provided by Google to start a service for our application, which is relatively flexible, so I adopted this method.

Web Server for Chrome

Choose Foloer, select our dist folder, select Automatically show index.html to enable the service, and you can access the application using the link below. Accessible on Local Network also generates another address that allows us to access the application on the phone.







Manifest.json List of web applications

Manifest.json provides the ability to add WebApp to the device’s home screen. See more configuration details here. We can use it to set ICONS, launch animations, background colors and more for our applications. It is under public of our project:

// public/manifest.json // basic configuration content {"name": "browse our experiment!" , "short\_name": "BrowseExp", "icons": \[ { "src": "/img/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/img/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } \], "start\_url": "/index.html", "display": "standalone", "background\_color": "#000000", "theme\_color": "#4DBA87" }Copy the code

When a browser (a browser that supports this feature) detects a manifest.json file in a directory, it reads its contents. When appropriate, a dialog box will pop up asking if you want to add the application to the desktop. Note that it does not pop up on the first visit, but when you find that the user has visited the site multiple times within a certain period of time. During development we can click Application -> Manifest -> Add to homescreen to trigger the pop-up box.

Other minor issues with mobile

As a mobile Web app, we need to solve some common problems, such as:

  • The browser style is unified
  • Mobile terminal click 300ms delay problem
  • Some event
  • The use of the rem

1. The styles of all browsers are unified

A common practice is to introduce normalize.css to reset the default styles on our devices so that they are highly consistent across browsers, and avoid unexpected changes in our layouts.

2. Click the 300ms delay and penetration event

Because our mobile browser needs to determine if the user wants to double click to zoom in, there is a 300ms delay to see if the user double clicks the screen; The click event is when we mix touch and click events. After the touch event response, if the element is hidden, then 300ms later the click event of the underlying element in the same location will be triggered. A common solution to these problems is to introduce fastclick.js, a library that modifies the browser’s touch event to simulate a click event and blocks the browser’s click events after 300ms. Let front-end developers write code with the familiar click

3. The use of rem

On the mobile end, rem is often used for responsive layout. We usually set the FONT size of HTML to 62.5%, so our 1REM = 10px is convenient for unit conversion.

Project deployment

Once developed, we need to deploy our project to our own server

Writing a service

First we write a back-end service that allows us to access the project’s index.html file, using express as the starting service.

// browse-exp.js
const fs = require('fs')
const path = require('path')
const express = require('express')

const app = express();

app.use(express.static(path.resolve(\_\_dirname, './dist')))
app.get('\*', function(req, res) {
  const html = fs.readFileSync(path.resolve(\_\_dirname, './dist/index.html'), 'utf-8')
  res.send(html)
})

app.listen(3002, function() {
  console.log('server listening on port 3002!')
})Copy the code

Then upload the project to the server through tools such as FTP. The server I use is Nginx, which is characterized by lightweight, high concurrency and configurable reverse proxy. We then need to configure a proxy to proxy our access to the server to the project. Create our configuration file holyzheng-top-3002.conf in /etc/nginx/conf. d

\ # etc/nginx/conf. D/holyzheng - top - 3002. The conf # as an example, on behalf of our application upstream browseexp {server 127.0.0.1:3002; } # transfer HTTP access to our project to HTTPS server {listen 80; # server\_name browseexp. Holyzheng.top; Error \_page 405 =200 @405; local@405 {proxy\_pass http://browseexp; } rewrite ^(.\*) https://$host$1 permanent; } # configure proxy to delegate browseexp. Holyzheng. Top to 127.0.0.1:3002 # server\_name browseexp.holyzheng.top; Configure SSL on; ssl\_certificate /etc/nginx/cert/1538045542271.pem; ssl\_certificate\_key /etc/nginx/cert/1538045542271.key; ssl\_session\_timeout 5m; ssl\_protocols SSLv2 SSLv3 TLSv1; ssl\_ciphers ALL:! ADH:! EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl\_prefer\_server\_ciphers on; Rewrite ^(. *) https://$host$1 permanent; rewrite ^(. *) https://$host$1 permanent; } location / { proxy\_set\_header X-Real-IP $remote\_addr; proxy\_set\_header X-Forward-For $proxy\_add\_x\_forwarded\_for; proxy\_set\_header Host $http\_host; proxy\_set\_header X-Nginx-Proxy true; proxy\_pass http://browseexp; # instance to proxy}}Copy the code

So we can access the project by accessing the domain name. The corresponding QR code is given here, which can be accessed and viewed:


Automatic identification of https://browseexp.holyzheng.top (qr code)

The following is the result of visiting the UC browser on Android (UC supports PWA very well). After a few visits to our application, relevant prompts pop up. Click “OK” to add to the home screen.




Personal blog

More front-end technology articles, art design, wordpress plug-ins, optimization tutorials, learning notes in my personal blog Meorong – describe life with you, welcome to exchange and learn together, progress together: http://panmiaorong.top

Article recommendation:

Here are some of the top tips for interviewing in 2018

Super easy to use development tools, programmer utility collation

Dry goods sharing: Vue2.0 to do mobile terminal development used in the relevant plug-ins and experience summary

Several cross-domain schemes in the front end

Vue Axios encapsulation and API interface management


Document a project from development to deployment based on VUE, typescript, and PWA