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:
- UI component interactions
- Call the unified API service request function
- Send requests using wrapped request.js
- Get the return of the server
- 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