preface

I’ve been working on how multi-page apps can have an elegant development model like a SPA

This set of architecture in the project feel good (has run hundreds of pages on the project), so we decided to open source to everyone

Reading this article can be achieved in the project use ES6 (7) + componentization (. Vue. | JSX) multi-page application development

If you don’t need SEO, you need front to back separation, and your project is a multi-page application, I’m the one to do it

(Actually, I want to use it as scaffolding for your multi-page application.)

Directory Structure

TIPS: The architecture of any project is related to the directory structure, so this section is very important. Please read it carefully

Let’s take a macro look at the structure

|--- public // Files required for production environment
    |--- components
    |--- css
    |--- fonts
    |--- images
    |--- js
    |--- sass
    |--- views
|--- src
    |--- components
    |--- css
    |--- fonts
    |--- images
    |--- js
    |--- sass
    |--- viewsCopy the code

Let’s expand on how a specific page should correspond to its resources. Take JS and views for example

|--- views
    |--- home // The official website introduces the business module
        |--- index.html
        ...
    |--- shopping // Shopping business module
        |--- buy.html
        ...
|--- js
    |--- lib
        |--- vue.js
        |--- react.js
        |--- react.dom.js
        ...
    |--- home // The official website introduces the js of business module
        |--- index.js
        ...
    |--- shopping // Shopping business module js
        |--- buy.js
        ...
    tools.js
    common.jsCopy the code

In multi-page applications, our pages are often divided into business modules, which consist of many pages. For example, home and shopping may be the business modules of the official website introduction and shopping respectively. Under this business module, there are many pages respectively, so our JS files also need to be named one-to-one correspondence.

Of course, we also have third-party JS libraries that don’t need to be compiled, so we use a special lib folder to store them. (Include your own instructions or filter, etc., do not need to compile, also directly in the lib can be imported)

In addition, you can also write your own libraries that need to be compiled directly into the js directory (e.g., tools.js,common.js).


The same goes for our Sass

|--- sass
    |--- home
        |--- index.scss
        ...
    |--- shopping
        |--- buy.scss
        ...Copy the code

They will compile files under CSS and JS respectively as

|--- css // SCSS compiled
    |--- home
        |--- index.css
    |--- shopping
        |--- buy.css
|--- js // after Babel processing js
    |--- home
        |--- index.js
    |--- shopping
        |--- buy.jsCopy the code

The path referenced by the page is (home/index.html for example)

. <link rel="stylesheet" href=".. /.. /js/css/home/index.css">... <script src=".. /.. /js/lib/vue(react).js"></script>
<script src=".. /.. /js/lib/react.dom.js"></script>
<script src=".. /.. /js/home/index.js"></script>.Copy the code

With js and Sass in place, the challenge is to know which entry JS file to compile during component writing. So we need some convention for our component name, which is the premise that convention is greater than configuration.

|--- components
    |--- home // home Service module
        |--- home-header.vue(jsx)
        |--- index-info.vue(jsx)
        ...
    |--- shopping  // Shopping business module
        |--- buy-list.vue(jsx)
        ...Copy the code

Our business module name under Components is the same as sass, JS before. Specific components are different.

We have several types of components

  • The components used by the current page
  • Common components under the current service module
  • Common components for all business modules

The name of the current page component is [page]-[component].vue(JSX).

The following

|--- components
    |--- home
        |--- index-info.vue(jsx)Copy the code

The index-info component is only used in the home/index. HTML page. When you modify the component, it will automatically compile the home/index.js intersection JS file and refresh the page.

The common component under the current business module is [business module]-[component].vue(JSX).

The following

|--- components
    |--- home
        |--- home-header.vue(jsx)Copy the code

The home-header component is a common component in the home business module. When you modify this component, it automatically compiles all js files in the home business module and refreshes the page.

What is left is the common components under all business modules, which we have agreed to place in the Components /common directory without naming conventions

|--- components
    |--- common
        |--- loading.vue(jsx)Copy the code

This loading component is a common component under all business modules. When you modify this component, it automatically compiles js files under all business modules and refreshes the page.

The rationale for compiling components and why conventions are named is as follows:

I will read the folder name, component name, and compile the intersection JS corresponding to the name according to the component changes

At this point, we have solved the component problem as well

Since I’m using the main gulp webpack, webpack is only compiled, so the compilation is almost instantaneous. Much faster than building with WebPack alone. If webpack is only used to build, entry and HTMLPlugin need to be configured. So it’s a lot slower, but mine doesn’t have to be that complicated.

Image && font files

This is actually a big crater

Our goal is for the component to import an image or font file relative to the path

<template> <figure> <img SRC =".. /.. /images/home/logo.jpg" Alt =" head "> </figure> </template> // In style like this <style rel="stylesheet/ SCSS "lang="sass"> @import ".. /.. /sass/home/index-info"; #bg h3 {background: url(".. /.. /images/holmes.jpg"); color: #fff; } </style>Copy the code

This pit, it is really indescribable, I personally tried a variety of positions to get this pit configured.

I’ll just show you what the final implementation looks like.

Dev’s path is such that the page can display images or fonts.

The build path looks like this

This has reached the development and release of the resource unity, explore this step is really very tired T.T, interested in their own source code.

Configuration of environment variables

We often encounter problems in WebPack with different configurations in different environments

You can first configure a script in package.json

// package.json
"scripts": {
    "build": "NODE_ENV=production gulp build"."dev": "NODE_ENV=dev gulp reload"
},Copy the code

If we need to configure different API request addresses for different environments, we can use the NODE_ENV we set in package.json to identify the current environment (I did this in gulpfile, so NODE_ENV can be identified directly in the file, as follows).

// src/js/ajaxurl.js

const server1 = 'https://production.server.com';
const server2 = 'https://dev.server.com';

let useServer = null;
if(NODE_ENV === 'production') {
    useServer = server1;
} else if(NODE_ENV === 'dev') {
    useServer = server2;
}

export default useServer;Copy the code
// src/js/home/index.js

import url from '.. /ajaxurl';
console.log(url);Copy the code

This solves the problem of having different configurations for different environments. I have dev and production configured by default, so you can expand on them. Such as

If you need to configure tests in development, you can write NODE_ENV=test gulp reload.

Another NODE_ENV=preproduction gulp build is available if pre-published packaged tests are required.

Gulp build is used for packaging and gulp reload is used for development.

Matters needing attention

NPM run dev (BTW, don’t forget to go to gulpfile.js and replace yourCDNLink with const CDN = ‘yourCDNLink’)

Naming must follow the convention! Naming must follow the convention! Naming must follow the convention!

Otherwise I don’t know who to compile!!

Gulp configuration is very simple, you can take a look at their own project to modify, don’t know can directly ask me.

If you don’t completely separate the front and back ends, it’s ok to put this SRC directly in the background directory.

TODO

  • [] Unit test of the project
  • [] Project Cli scaffolding

The latter

It was supposed to be vue-cli or create-react-app cli scaffolding, but! I am really too lazy and have no time! You can try clone first, if enough people like it, I will write it as cli, release NPM 🙂

I used MAC to complete the development, and spent more than half a day to write compatibility for Windows. Windows may have bugs, not me! Window is spicy chicken!

Finally, let me show you the structure of one of our projects.


The overview

The overview

Js part

Js part

images

images

component

Components and pages

You may notice more apis and mock folders in the overview diagram. This is our Promise encapsulating interface layer and front-end local mock layer. Since each team has a different approach, I didn’t put it in the scaffolding this time

Vue-multpage General Edition: github.com/MeCKodo/vue…

This is our internal version


Have a nice day