The template is based on vuE-CLI4 and VUant-UI, and best practices for large H5 project development. Let’s take a look

Use your cute little hands to light up a star

The project structure

This project has generated a complete development framework for you, below is the directory structure of the entire project.

├ ─ ─. Dead simple# git log

├ ─ ─ the plop - templates# Basic template

├ ─ ─ the public# static resources

│ │ ─ ─ the favicon. Ico# the favicon icon

│ └ ─ ─ index. HTML# HTML templates

├ ─ ─ the SRC# source code

│ ├ ─ ─ assets# static resources

│ ├ ─ ─ the components# Global common component

│ ├ ─ ─ constants# constants

│ ├ ─ ─ the core# layered

│ ├ ─ ─ enum# enumeration

│ ├ ─ ─ filters# global filter

│ ├ ─ ─ the ICONS# Project all SVG ICONS

│ ├ ─ ─ lang# Internationalization language

│ ├ ─ ─ layout# the overall layout

│ ├ ─ ─ the router# routing

│ ├ ─ ─ store# Global Store management

│ ├ ─ ─ styles# global style

│ ├ ─ ─ utilsGlobal public method

│ ├ ─ ─ pages# pages All pages

│ ├ ─ ─ pwa# Progressive Web applications

│ ├ ─ ─ App. Vue# Entry page

│ ├ ─ ─ the main js# entry file load component initialization etc

│ └ ─ ─ permission. Js# Permission management

├ ─ ─ tests# test

├ ─ ─ editorconfig# Code Style

├ ─ ─. Env. XXX# Environment variable configuration

├ ─ ─. Eslintrc. Js# esLint configuration item

├ ─ ─. Sentryclirc. JsConfigure front-end exception log monitoring

├ ─ ─. Babel. Config# Babel configuration

├ ─ ─ plopfile. JsBasic template configuration

├ ─ ─ vue. Config. Js# vue - cli configuration

├ ─ ─ postcss. Config. Js# postcss configuration

└ ─ ─ package. Json# package.json

.

Copy the code

The installation

# Clone project

git clone https://github.com/push-over/vue-h5-template.git



Enter the project directory

cd vue-h5-template



# install dependencies

npm install



# Do not install NPM with CNPM. There will be various weird bugs

npm install --registry=https://registry.npm.taobao.org



# Local development start project

npm start

Copy the code

TIP

It is strongly recommended not to use CNPM installation directly, there will be various weird bugs, you can re-specify Registry to solve the problem of slow NPM installation. If the problem persists, use YARN to replace NPM.

If the Installation fails for Windows users, node-sass installation may fail. Solution

Because Node-sass is python dependent, you’ll need to check out the installation tutorials if you haven’t installed and configured them before.

After the startup is complete, the browser will automatically open to visit [http://localhost:9000, you see the following page represents a successful operation.

Next you can modify the code for business development, the project built typical business templates, simulation data, state management, internationalization, global routing and so on a variety of practical functions to assist development

Common commands

# Project packaging

npm run build:xxx



# auto create

npm run new



Git commit

npm run git-cz



# generate CHANGELOG

npm run genlog

Copy the code

Layered architecture

At present, a development trend of the front end is to build a single page application (SPA). When your application is large, or your application’s business logic is complex enough, there are all kinds of problems. Let’s mention just two:

  • When a product requires multiple people to collaborate, each person has a different code style and understanding of the business, resulting in a messy distribution of business logic

  • The understanding of the product stays at the page-driven level, resulting in a large discrepancy between the implemented technical model and the actual business model, which can be easily destroyed when business requirements change

  • .

In view of the above problems, we use the following architecture diagram to explain:


The View layer /View layer is the one that we contact most, and I think we all know it well. I won’t introduce it here, but I will focus on the other several layers:

Services layer

The Services layer is used to manipulate underlying technologies, such as encapsulating AJAX requests, manipulating browser cookies, LocaStorage, IndexedDB, and Native capabilities (such as calling cameras, etc.). And establish Websocket to interact with the back end.

Axios encapsulation

.



export default async function(options) {

const { url } = options

const requestOptions = Object.assign({}, options)



try {

const { data, data: { errno, errmsg }} = await instance.request(requestOptions)

if (errno) {

errorReport(url, errmsg, requestOptions, data)

throw new Error(errmsg)

}

return data

} catch (err) {

errorReport(url, err, requestOptions)

throw err

}

}

Copy the code

IndexedDB

.



export class DBRequest {

instance



static getInstance() {

if (!this.instance) {

this.instance = new DBRequest()

}

return this.instance

}

async create(options = {}) {

const { name, data } = options

const db = await indexDB(name)

return await db.add(name, data)

}

.

}



Copy the code

.

Entities layer

Entity is the core concept of domain-driven design. It is the carrier of domain services, which defines the attributes and methods of an individual in a business. The key to distinguishing an object from an entity is whether it has a unique identifier (such as id).


As can be seen from the above code, it is mainly the attributes and derived attributes of the entity itself. Of course, the entity itself can also have methods to implement business logic belonging to the entity itself.

Not all entities should be wrapped into a class as described above. If the business logic of an entity itself is simple, there is no need to wrap it, as Test in this template is just a demonstration.

Interactors layer

The Interactors layer is the layer responsible for handling business logic and consists primarily of business use cases

import { Request } from '@/utils/request'

import { CARDS } from '@/constants/api/test'



class TestHttpInteractor {

service

constructor(service) {

this.service = service

}

async getTest() {

try {

const options = { url: CARDS }

return await this.service.get(options)

} catch (error) {

throw error

}

}

async createTest(data) {

try {

const optons = { url: CARDS, data }

await this.service.post(optons)

} catch (error) {

throw error

}

}



.

}



const testHttpInteractor = new TestHttpInteractor(Request.getInstance())

export default testHttpInteractor

Copy the code

As you can see from the above code, the Sevices layer provides a class instance through the Interactors class constructor, which can achieve the decoupling between the two layers, and quickly switch services. Of course, there are some differences between DI and this. But that’s what we need.

In addition, the Interactors layer can obtain the entity class provided by the Entities layer, and provide the View layer with the business logic provided by the Interactors layer. For example:


Of course, this layered architecture is not a silver bullet. It is mainly suitable for scenarios where entity relationships are complex and interactions are relatively stereotypical, such as enterprise software. On the contrary, simple entity relationships and complex interactions are not suitable for this hierarchical architecture.

Then it’s important to be clear that architecture is not the same as the project file structure, which is how you visually separate parts of your application, while architecture is how you conceptually separate your application. You can choose different file structures while maintaining the same architecture. There is no perfect file structure, so choose the one that works for you depending on your project.

layout

The overall layout of a page is the outermost framework structure of a product. Vue-router routing is nested here, so in general, adding or modifying pages only affects the main area of the app-main. Everything else in layout, such as the bottom navigation, does not change as your main page changes.

/foo                                  /bar

+------------------+ +-----------------+

| layout | | layout |

| +--------------+ | | +-------------+ |

| | foo.vue | | +------------> | | bar.vue | |

| | | | | | | |

| +--------------+ | | +-------------+ |

+------------------+ +-----------------+

Copy the code

Here, a layer of keep-alive is wrapped outside app-main mainly for caching. If not necessary, it can be removed by itself.


style

CSS Modules

During style development, two issues stand out:

  • Global pollution – selectors in CSS files are globally valid. Selectors in different files with the same name are overwritten by later styles depending on the order in the build file.
  • Selector complex – in order to avoid the above problems, we have to careful when writing style, in the name of the class will take limits, is becoming more and more long, people development also it is easy to lead to chaos, naming style selector used by an element number may also more and more, eventually lead to difficult to maintain.

Fortunately, VUE provides scoped to solve the above problems. It adds the concept of a domain to CSS as the name suggests.

/* Before compiling */

.example {

color: red;

}



/* After compiling */

.example[_v-f3f3eg9] {

color: red;

}

Copy the code

Just add style scoped so that CSS only applies to the current component.

TIP

With scoped, the style of the parent component does not permeate into the child components. However, the root node of a child component is affected by both its parent’s Scoped CSS and the child’s scoped CSS. This is designed so that the parent component can adjust the style of the root element of its child component from a layout perspective.

The directory structure

Vue-h5-template All global styles are set in the @/ SRC /styles directory

├ ─ ─ styles

│ ├ ─ ─ _animation# global animation

│ ├ ─ ─ index. SCSS# Global universal style

│ ├ ─ ─ _mixin SCSS# global mixin

│ ├ ─ ─ _transition SCSS# Transition effect

│ └ ─ ─ _variables SCSS# global variables

Copy the code

A complete interaction with the server

In VuE-h5-Template, a complete front-end UI interaction to server processing flow looks like this:

  1. UI component interactions
  2. Call the unified API service request function
  3. Send requests using wrapped request.js
  4. Get the return of the server
  5. Update the data

request.js

@/ SRC /utils/request.js is the secondary encapsulation of HTTP based on the Server directory, facilitating unified processing of POST, GET and other requests. See the project code for details.

.

export class Request {

instance



static getInstance() {

if (!this.instance) {

this.instance = new Request()

}

return this.instance

}



async post(options = {}) {

const { data } = await service({

method: 'post'.

. options

})

return data

}

.

}



Copy the code

example

Defines the interface address unified management SRC/constants/API/test. The js

export const CARDS = '/admin/cards'

Copy the code

Request method SRC/core/interactors/test – interactor. Js

async getTest() {

try {

const options = { url: CARDS }

return await this.service.get(options)

} catch (error) {

throw error

}

}

Copy the code

Request mode SRC /utils/request.js

async get(options = {}) {

const { data } = await service({

method: 'get'.

. options

})

return data

}

Copy the code

TIP

Don’t get tangled up in the directory structure

The page uses SRC /pages/test/index.vue

# Lifecycle

async created() {

if (this.id) {

await this.handleGetTest()

}

}



# request

async handleGetTest() {

try {

const test = await testInteractor.getTest(this.id)

this.addressInfo = Object.assign({}, test)

} catch (error) {

console.log(error)

}

}

Copy the code

We may feel very cumbersome, so many files easy to confuse, repeated code and so on, do not worry, this template configuration automatic file generation, in addition to the View /View layer you need to manually write code, the other we will go to a key generation, next we will talk about the use of methods.

Generate required files

During development, whether we add pages or components, etc. You need to keep creating.vue files (or other frameworks or HTML/JS/CSS files)

In the case of a Vue project, when we create a component or view, we create a.vue file and write

Since this repetitive tasks, and not the actual operation difficulty, we won’t learn anything, that is there any way to say goodbye to hand knock, here to introduce a plugin plop, its use is more simple, I don’t do too much introduced here, you can refer to the document, or directly pull the template for reference

In this project, I have configured 5 items. What do they represent respectively?

module.exports = function(plop) {

plop.setGenerator('page', pageGenerator) // Page

plop.setGenerator('component', componentGenerator) / / component

plop.setGenerator('store', storeGenerator) // vuex

plop.setGenerator('interactor', interactorGenerator) // Business logic

plop.setGenerator('db-interactor', dbInteractorGenerator) //db business logic

}

Copy the code

TIP

The template creation directive is NPM run new, remember to belong to the directory or file name

DSBridge

Key features of DSBridge

  • DSBridge is truly cross-platform, officially supporting both ios and Android.
  • DSBridge supports synchronous invocation.
  • Three-end friendly; Whether it is on ios, Android or the Web, it is very simple and elegant to use, which is an art compared to web view javascript Bridge.
  • DSBridge is a Chinese project with detailed Chinese documentation and feedback channels.

H5 page communicates with Native

  • Cross-platform; Supports both ios and Android.
  • Two-way call; Js can call native, native can call JS
  • Support not only asynchronous invocation, but also page synchronous invocation (DSBridge is the only javascript Bridge that supports synchronous invocation)
  • Support for progress callback, multiple returns (often used for file download progress, timers, etc.)
  • Android supports Tencent X5 kernel
  • Three terminals easy to use; It’s easy to use on either the front end or android or ios, greatly reducing integration/learning costs

Environment variables and configuration files

env

# mobile terminal console (yes) | close (no)

VCONSOLE=no



# titles

VUE_APP_TITLE=CHINA-GOODS-H5



# port

DEVSERVERPORT=9000



# Error monitoring platform

SENTRY_ENABLED=yes

SENTRY_DSN='https://[email protected]/3619515'

SENTRY_PLUGIN_ENABLED=no

Copy the code

settings

export const TITLE = ' '      			/ / title

export const TOKEN_KEY = ' ' // token-key

export const LANGUAGE_KEY = 'language' / / the internationalization

.

Copy the code

ESLint .editorconfig

Whether it’s a multi-person collaboration or a personal project, code specification is important. Doing so not only largely avoids basic syntax errors, but also keeps the code readable.

All configuration files for ESLint are in.eslintrc.js. The basic specification of this project is based on the official VUE ESLint rule eslint-config-vue with a few modifications. You can customize the configuration according to your own needs.

The code style is in. Editorconfig, which you can customize as you like.

SVG icon

If you do not find the required Icon in the project Icon, you can go to Iconfont.com to select and generate your own business Icon library, then use it. Or any other SVG icon site, just download SVG and put it in a folder.


Generate icon library code

First, search for the icon you want and collect it in your shopping cart. In the shopping cart, you can add the selected icon to the project (if not, create a new one) and then generate resources/code on the project dimension.


This project now supports and recommends the introduction of SVG exports alone. Download method as shown below:


After downloading, place the downloaded.svg file in the @/ ICONS/SVG folder and it will be automatically imported.

Optimize your OWN SVG even further

Directives already configured, only need to execute the relevant directives:

npm run svgo

Copy the code

use

<svg-icon icon-class="password" /> // icon-class is the name of icon

Copy the code

internationalization

This project is a collection of international I18N solutions. Through vuE-I18N.

Since the UI framework of this project uses Vant UI, it needs to be internationalized as well as internationalized. At the same time, the current lang language is stored in the cookie, in order to open the page next time can remember the last language setting.

export const VueVantLocales = (lang = getLocale()) = > {

switch (lang) {

case 'zh':

Locale.use('zh-CN', vantZhLocale)

break

case 'en':

Locale.use('en-US', vantEnLocale)

break

}

}



export default new VueI18n({

locale: getLocale(),

fallbackLocale: getLocale(),

messages

})

Copy the code

use

Use in Html:

// $t is a global method provided by vue-i18n

$t('heoll')

Copy the code

Js using:

const options = [

{

value: '1'.

label: this.$t('i18nView.one')

},

{

value: '2'.

label: this.$t('i18nView.two')

}

]

Copy the code

Style adapter

Because this template is H5 development template, so must have a style match. For this, the mainstream solutions include VW and REM. We will use a tool to help us complete screen adaptation, postcss-px-to-viewport. After installation, we only need to configure postcss.config.js, please refer to the document for specific configuration instructions.


Debug console

In terms of debugging, this project uses vConsole as the mobile debugging panel. The function is equivalent to opening the PC Console, and you can easily view key debugging information such as Console, Network, Element and Storage.

Error monitoring platform

I don’t know much about other error monitoring platforms, except that I used Sentry when I was writing PHP, so I configured it as the error monitoring platform in this project. The Babel plugin, which automatically adds error reporting functions to a try catch, is configured in the.sentryclirc file and will be prompted when you create it. If not, see configuring Sentry

[defaults]

url=https://sentry.io

Org = organization name

Project = project name



[auth]

token=token

Copy the code

GIT Submission Style

The code commit log is a good code change log. Regular code submission records are extremely important in the maintenance and development of code, as well as in locating bugs or rolling back versions.

Related instructions

npm run git-cz

Copy the code

Detailed instructions

1. Select the type of change that you're committing

Select the type of change you want to commit



2. What is the scope of this change (e.g. component or file name): (press enter to skip)

What is the scope of the change (for example, component or filename) :(press Enter to skip)



3. Write a short, imperative tense description of the change (max 61 chars)

Write short imperative tense descriptions (up to 61 characters)



4. Provide a longer description of the change: (press enter to skip)

Provide a detailed explanation of the changes :(press Enter to skip)



5. Are there any breaking changes?

Have there been major changes?



6. Does this change affect any open issues?

Does this change affect any outstanding issues?



- feat New function

- fix Fixes bugs

- docs Updates the document

- Style code format, punctuation update

- refactor Reconstructs the code

- PerF performance optimization

- test Updates the test

- build Builds the system or depends on package updates

- ci Updates CI configurations and script files

- chore non-src or test file updates

- Revert COMMIT Rollback

Copy the code

Generate the CHANGELOG. Md

Related directives have also been configured:

npm run genlog

Copy the code

A file format similar to this appears:

### Features



* Internationalization interceptor completion template ([379b452](https:/ / 10.6.30.204 / front/China - goods - h5 / commits / 379 b4522f9c0c0a1c282281af68c92c1cca10858))

* Drop into shopping cart ([f1a5f2d](HTTPS:/ / 10.6.30.204 / front/China - goods - h5 / commits/f1a5f2db2fe6e67e3b5801c26563ba9f089e470b))

Copy the code

PWA

PWA is an abbreviation of Progressive Web App, which translates as Progressive Enhancement Web application. It was introduced by Google in 2016 and launched in 2017. The purpose is to make use of the standardized framework provided by the mobile terminal to achieve progressive web applications with similar user experience to native applications in web applications.

  • You can generate small desktop ICONS without opening a browser, facilitating user access
  • Network cache is used to improve the speed of page access to achieve progressive page access or even offline access to improve user experience
  • Implement the push function similar to app and generate system notification to push to users

The latest scaffolding of Vue integrates the plug-in of PWA, which makes the implementation of PWA more simple. Just configure the PWA attribute in the vue.config.js file to automatically generate the corresponding service-worker.js configuration file, which will not be described too much.

WebPack configuration

Some Configuration instructions

# PWA

pwa: {

name: VUE_APP_TITLE,

workboxPluginMode: 'InjectManifest'.

workboxOptions: {

swSrc: resolve('src/pwa/service-worker.js')

}

}



# alias

configureWebpack: {

name: VUE_APP_TITLE,

resolve: {

alias: {

The '@': resolve('src')

}

}

},



In order to avoid the problem of introducing variables separately for each use, style-resources-loader is adopted

pluginOptions: {

'style-resources-loader': {

preProcessor: 'scss'.

patterns: [

resolve('src/styles/_variables.scss'),

resolve('src/styles/_mixins.scss')

]

}

},



# vconsole

config.plugin('VConsolePlugin')

.use(new VConsolePlugin({

filter: [].

enable: DEV && VCONSOLE === 'yes'

}))

.end()



# introduce lodash in the page can be directly used _.isString()...

config.plugin('ProvidePlugin')

.use(new webpack.ProvidePlugin({

_: 'lodash'

}))

.end()



# set SVG - Sprite - loader

config.module

.rule('svg')

.exclude.add(resolve('src/icons'))

.end()

config.module

.rule('icons')

.test(/\.svg$/)

.include.add(resolve('src/icons'))

.end()

.use('svg-sprite-loader')

.loader('svg-sprite-loader')

.options({

symbolId: 'icon-[name]'

})

.end()



Submit the map file

config.plugin('sentryPlugin')

.use(new SentryPlugin({

release: version,

include: path.join(__dirname, './dist/static/js'),

urlPrefix: '~/vue-h5-template/statis/js'.

ignore: ['node_modules']

}))

.end()

Copy the code

Related to the plug-in

  • vconsole-webpack-plugin

  • @sentry/webpack-plugin

  • lodash-webpack-plugin

.

Some details are also done in the project. For details, please pull the project to view. Thank you for watching. If you feel good, you can give a STAR template address, which will be updated continuously. If you have any questions, you can leave a message or add me Wechat Gao1336650475