1 installation vue – cli3.0

0 Taobao Mirror

npm install -g cnpm --registry=https://registry.npm.taobao.org
Copy the code

1 installation vue – cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli
Copy the code

2 Viewing the Version

vue --version
Copy the code

3 Vue-CLI construction project

vue create vue-demo
Copy the code

Select default to enable service

4 Directory Structure

├ ─ ─ the README. Md # # explain | - dist folder after packaging ├ ─ ─ Babel. Config. Js # Babel grammar compiler ├ ─ ─ package - lock. Json ├ ─ ─ package. The json ├ ─ ─ public # ├─ ├─ SRC # ├─ ├─ favicon├─ app.vue - Page
├── Assets - Static Catalogue
│ └ ─ ─ logo. PNG
├ ─ ─ components components
│ └ ─ ─ the HelloWorld. Vue
├ ─ main.js # Import file, load public components| - vue. Config. Js # config file. | - eslintrc. Js # ES - lint check. | - gitignore # git ignore the upload file format | -- Babel. Config. Js # Babel grammar compiler | -- Package. json # Basic project informationCopy the code

Standard VUE directory structure

2 Environment variables and modes

0 is introduced

In NPM, the environment variables and mode are already determined when vue-CLI is actually started, so that the code can be easily built

After opening the package. The json

The environment that we’re describing is in scripts

1 mode

Is an important concept in the Vue CLI project. By default, a Vue CLI project has three modes:

  • developmentPattern is used tovue-cli-service serve
  • productionPattern is used tovue-cli-service build 和 vue-cli-service test:e2e
  • testPattern is used tovue-cli-service test:unit

You can override the default mode for the command line by passing the –mode option argument. For example, if you want to use development environment variables in build commands, include them in your package.json script


2 call

So how do we call it in code, and its application scenario

process.env.NODE_ENV
Copy the code

So we can get his environment variables

Three scenarios

Create a new config in the SRC directory to create env.js

let baseUrl = ' ';

const env = process.env
if (env.NODE_ENV == 'development') {
    baseUrl = ` http://192.168.1.1 `; // Address of the development environment
} else if (env.NODE_ENV == 'production') {
    baseUrl = ` http://192.168.1.2 `; // Production environment address
} else if (env.NODE_ENV == 'test') {
    baseUrl = ` http://192.168.1.3 `; // Address of the test environment
}

export {
    baseUrl,
    env
}
Copy the code

So this way we can just use it in different environments

3 Internet Explorer compatible processing, remove console

npm install @babel/polyfill -s

npm install babel-plugin-transform-remove-console -s
Copy the code

The configuration in babel.config.js is as follows


const plugins = []
if (process.env.NODE_ENV === 'production') {
  / / remove the console log
  plugins.push('transform-remove-console')}module.exports = {
  presets: [['@vue/app', {
      polyfills: [
        'es6.array.iterator'.'es6.promise'.'es7.promise.finally'.'es6.symbol'.'es6.array.find-index'.'es7.array.includes'.'es6.string.includes'.'es6.array.find'.'es6.object.assign'
      ]
    }]
  ],
  plugins
}
Copy the code

4 VUE – CLI basic configuration

Create a vue.config.js folder and start to configure vue-CLI

module.exports = {
    // The base URL when deploying the application package
    publicPath: process.env.NODE_ENV === 'production' ? '/online/' : '/'.// Directory of the production environment build file generated when vue-cli-service build is run
    outputDir: 'dist'.// Place the generated static resources (js, CSS, img, fonts) in the directory (relative to outputDir)
    assetsDir: 'assets'.// eslint-loader checks whether the @vue/cli-plugin-eslint installation is valid while saving
    lintOnSave: true.// Whether to use the Vue build with the runtime compiler. After setting true, you can use template again
    runtimeCompiler: true.// Whether the production environment generates the sourceMap file see the end for details about sourceMap
    productionSourceMap: false,}Copy the code

5 Adding An Alias

Create a vue.config.js folder and start to configure vue-CLI

1 Alias Configuration

const path =  require('path'); // Introduce path module (node)
const resolve = (dir) = > path.join(__dirname, dir); // Form files into absolute paths
 
module.exports = {
    chainWebpack: config= > {
        // Add an alias
        config.resolve.alias
          .set(The '@', resolve('src'))
          .set('assets', resolve('src/assets'))
          .set('components', resolve('src/components'))}}Copy the code

2 Application Scenarios

The directory structure may be layered on top of each other before reaching the directory

For example, the env.js directory

import {baseUrl} from '.. /config/env'
Copy the code

But we don’t guarantee that the directory is that close, so what do we do

// @ represents the SRC directory

import {baseUrl} from '@/config/env'
Copy the code

7 Optimization – Configure externals

Prevent packages from being packaged into bundles, and instead obtain these extension dependencies externally at runtime



  • Vue
  • ELEMENT
  • VueRouter
  • Vuex
  • axios

1 Introducing framework

We’re going to pull out some of the packages that we’re outsourcing references and put them in public

2 edit externals

We are in the vue. Config.

module.exports = {

   configureWebpack: config= > {

       config.externals = {
         'vue': 'Vue'.'element-ui': 'ELEMENT'.'vue-router': 'VueRouter'.'vuex': 'Vuex'.'axios': 'axios'}}Copy the code

3 the introduction of CDN

In this case, we need to use public/index.html

<! DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" The content = "width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = 0" > < meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no"> <meta http-equiv="X-UA-Compatible" content="chrome=1" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="stylesheet" href="<%= BASE_URL %> CDN /element-ui/2.5.4/theme-chalk/index.css"> <link rel="stylesheet" href="<%= BASE_URL % > CDN/animate / 3.5.2 / animate. CSS "> < link rel =" stylesheet "href =" < % = BASE_URL % > CDN/iconfont / 1.0.0 / index. The CSS "> < link Rel = "stylesheet" href = "< % = BASE_URL % > CDN/iconfont 1.0.0 / iconfont CSS" > < link rel = "stylesheet" href = "< % = BASE_URL % > the CDN/iconfont 1.0.0 / index. The CSS "> < title > vue - demo < / title > < / head > < body > < noscript > < strong > We 'r e sorry but vue - demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <! -- Built-in files will be auto injected --> <script SRC ="<%= BASE_URL %> CDN /vue/2.5.2/vue.min.js" charset=" utF-8 "></script> < script SRC = "< % = BASE_URL % > CDN/vuex/against 2.4.1 / vuex. Min. Js" charset = "utf-8" > < / script > < script SRC = "< % = BASE_URL %> CDN /vue-router/3.0.1/ vue-router-min. js" charset=" UTF-8 "></script> <script SRC ="<%= BASE_URL % > CDN/axios / 1.0.0 / axios. Min. Js "charset =" utf-8 "> < / script > < script SRC =" < % = BASE_URL % > CDN/element - the UI / 2.5.4 / index. Js. "" charset="utf-8"></script> </body> </html>Copy the code

8 Optimization – Enable Gzip compression

1 introduction

Vue CLI 3.0 has a number of changes compared to 2.0. The most obvious change is that the build folder has been removed and replaced with the root directory vue.config.js

npm i -D compression-webpack-plugin
Copy the code

2 modify the vue. Config. Js

const CompressionPlugin = require("compression-webpack-plugin")

module.exports = {
	configureWebpack:config= >{
        if(process.env.NODE_ENV === 'production') {return{
                plugins: [
                    new CompressionPlugin({
                        test:/\.js$|\.html$|.\css/.// Match the file name
                        threshold: 10240.// Compress data over 10K
                        deleteOriginalAssets: false // Do not delete the source file}}},}Copy the code

3 Configure gzip for nginx

gzip  on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 6;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
Copy the code

Line 1: Enable Gzip

Line 2: do not compress the critical value, greater than 1K only compression, generally do not change

Line 3: buffer, which is, well, I won’t explain, don’t change

Line 4: With the reverse proxy, the terminal communication is HTTP/1.0, and those who need it should not read my popular science article. The default is HTTP/1.1

Line 5: compression level, 1-10, the larger the number of compression, the better, the longer the time, depending on the mood to change it freely

Line 6: the type of file to compress, what is missing on the line, JavaScript has two ways to write, best to write both, there are always people complain that js files are not compressed > >, in fact, write one more format is ok

第7行 : for Squid and other cache services, on would add “Vary: accept-encoding “to the Header. I don’t need it, so I’ll see what I can do

Line 8: IE6 is not so Gzip friendly, won’t it Gzip

9 Optimization – First screen loading


      
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = 0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no">
    <meta http-equiv="X-UA-Compatible" content="chrome=1" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <link rel="stylesheet" href="< % = BASE_URL % > CDN/element - UI - chalk/index / 2.5.4 / theme. CSS">
    <link rel="stylesheet" href="< % = BASE_URL % > CDN/animate / 3.5.2 / animate. CSS">
    <link rel="stylesheet" href="< % = BASE_URL % > CDN/iconfont / 1.0.0 / index. The CSS">
    <link rel="stylesheet" href="< % = BASE_URL % > CDN/iconfont 1.0.0 / iconfont CSS">
    <link rel="stylesheet" href="< % = BASE_URL % > CDN/iconfont / 1.0.0 / index. The CSS">
    <title>vue-demo</title>
    
   <style>
     html.body.#app {
       height: 100%;
       margin: 0px;
       padding: 0px;
     }

     .chromeframe {
       margin: 0.2 em 0;
       background: #ccc;
       color: # 000;
       padding: 0.2 em 0;
     }

     #loader-wrapper {
       position: fixed;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
       z-index: 999999;
     }

     #loader {
       display: block;
       position: relative;
       left: 50%;
       top: 50%;
       width: 150px;
       height: 150px;
       margin: -75px 0 0 -75px;
       border-radius: 50%;
       border: 3px solid transparent;
       /* COLOR 1 */
       border-top-color: #FFF;
       -webkit-animation: spin 2s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -ms-animation: spin 2s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -moz-animation: spin 2s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -o-animation: spin 2s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       animation: spin 2s linear infinite;
       /* Chrome, Firefox 16+, IE 10+, Opera */
       z-index: 1001;
     }

     #loader:before {
       content: "";
       position: absolute;
       top: 5px;
       left: 5px;
       right: 5px;
       bottom: 5px;
       border-radius: 50%;
       border: 3px solid transparent;
       /* COLOR 2 */
       border-top-color: #FFF;
       -webkit-animation: spin 3s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -moz-animation: spin 3s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -o-animation: spin 3s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -ms-animation: spin 3s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       animation: spin 3s linear infinite;
       /* Chrome, Firefox 16+, IE 10+, Opera */
     }

     #loader:after {
       content: "";
       position: absolute;
       top: 15px;
       left: 15px;
       right: 15px;
       bottom: 15px;
       border-radius: 50%;
       border: 3px solid transparent;
       border-top-color: #FFF;
       /* COLOR 3 */
       -moz-animation: spin 1.5 s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -o-animation: spin 1.5 s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -ms-animation: spin 1.5 s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -webkit-animation: spin 1.5 s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       animation: spin 1.5 s linear infinite;
       /* Chrome, Firefox 16+, IE 10+, Opera */} @ -webkit-keyframes spin {
       0% {
         -webkit-transform: rotate(0deg);
         /* Chrome, Opera 15+, Safari 3.1+ */
         -ms-transform: rotate(0deg);
         /* IE 9 */
         transform: rotate(0deg);
         /* Firefox 16+, IE 10+, Opera */100%} {-webkit-transform: rotate(360deg);
         /* Chrome, Opera 15+, Safari 3.1+ */
         -ms-transform: rotate(360deg);
         /* IE 9 */
         transform: rotate(360deg);
         /* Firefox 16+, IE 10+, Opera */}} @keyframes spin {
       0% {
         -webkit-transform: rotate(0deg);
         /* Chrome, Opera 15+, Safari 3.1+ */
         -ms-transform: rotate(0deg);
         /* IE 9 */
         transform: rotate(0deg);
         /* Firefox 16+, IE 10+, Opera */100%} {-webkit-transform: rotate(360deg);
         /* Chrome, Opera 15+, Safari 3.1+ */
         -ms-transform: rotate(360deg);
         /* IE 9 */
         transform: rotate(360deg);
         /* Firefox 16+, IE 10+, Opera */}}#loader-wrapper .loader-section {
       position: fixed;
       top: 0;
       width: 51%;
       height: 100%;
       background: #7171C6;
       /* Old browsers */
       z-index: 1000;
       -webkit-transform: translateX(0);
       /* Chrome, Opera 15+, Safari 3.1+ */
       -ms-transform: translateX(0);
       /* IE 9 */
       transform: translateX(0);
       /* Firefox 16+, IE 10+, Opera */
     }

     #loader-wrapper .loader-section.section-left {
       left: 0;
     }

     #loader-wrapper .loader-section.section-right {
       right: 0;
     }

     /* Loaded */
     .loaded #loader-wrapper .loader-section.section-left {
       -webkit-transform: translateX(100%);/* Chrome, Opera 15+, Safari 3.1+ */
       -ms-transform: translateX(100%);/* IE 9 */
       transform: translateX(100%);/* Firefox 16+, IE 10+, Opera */
       -webkit-transition: all 0.7 s 0.3 s cubic-bezier(0.645, 0.045, 0.355, 1.000);
       transition: all 0.7 s 0.3 s cubic-bezier(0.645, 0.045, 0.355, 1.000);
     }

     .loaded #loader-wrapper .loader-section.section-right {
       -webkit-transform: translateX(100%)./* Chrome, Opera 15+, Safari 3.1+ */
       -ms-transform: translateX(100%)./* IE 9 */
       transform: translateX(100%)./* Firefox 16+, IE 10+, Opera */
       -webkit-transition: all 0.7 s 0.3 s cubic-bezier(0.645, 0.045, 0.355, 1.000);
       transition: all 0.7 s 0.3 s cubic-bezier(0.645, 0.045, 0.355, 1.000);
     }

     .loaded #loader {
       opacity: 0;
       -webkit-transition: all 0.3 s ease-out;
       transition: all 0.3 s ease-out;
     }

     .loaded #loader-wrapper {
       visibility: hidden;
       -webkit-transform: translateY(100%);/* Chrome, Opera 15+, Safari 3.1+ */
       -ms-transform: translateY(100%);/* IE 9 */
       transform: translateY(100%);/* Firefox 16+, IE 10+, Opera */
       -webkit-transition: all 0.3 s 1s ease-out;
       transition: all 0.3 s 1s ease-out;
     }

     /* JavaScript Turned Off */
     .no-js #loader-wrapper {
       display: none;
     }

     .no-js h1 {
       color: # 222222;
     }

     #loader-wrapper .load_title {
       font-family: 'Open Sans';
       color: #FFF;
       font-size: 19px;
       width: 100%;
       text-align: center;
       z-index: 9999999999999;
       position: absolute;
       top: 60%;
       opacity: 1;
       line-height: 30px;
     }

     #loader-wrapper .load_title span {
       font-weight: normal;
       font-style: italic;
       font-size: 13px;
       color: #FFF;
       opacity: 0.5;
     }
   </style>
    
  </head>
  <body>
    <noscript>
      <strong>We're sorry but vue-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    
    <div id="app">
      <div id="loader-wrapper">
        <div id="loader"></div>
        <div class="loader-section section-left"></div>
        <div class="loader-section section-right"></div>
        <div class="load_title">Vue is loading, please wait patiently<br>
          <span>V1.3</span>
        </div>
      </div>
    </div>

    <! -- built files will be auto injected -->
    <script src="< % = BASE_URL % > CDN/vue / 2.5.2 / vue. Min. Js." " charset="utf-8"></script>
    <script src="< % = BASE_URL % > CDN/vuex/against 2.4.1 / vuex. Min. Js." " charset="utf-8"></script>
    <script src="< % = BASE_URL % > CDN/vue - the router / 3.0.1 vue - the router. Min. Js." " charset="utf-8"></script>
    <script src="< % = BASE_URL % > CDN/axios / 1.0.0 / axios. Min. Js." " charset="utf-8"></script>
    <script src="< % = BASE_URL % > CDN/element - the UI / 2.5.4 / index. Js." " charset="utf-8"></script>
  </body>

</html>

Copy the code

10 Preprocessor (Sass/Less/Stylus)

# Sass
npm install -D sass-loader node-sass

# Less
npm install -D less-loader less

# Stylus
npm install -D stylus-loader stylus
Copy the code
You can then import the appropriate file type, or use it in a *.vue file like this:  <style scoped lang="stylus"> .personal position relative .banner-red width 100% height 100px </style>Copy the code

11 Automatic node deployment

1 installation scp2

npm install scp2 --save-dev
Copy the code

2 Configure a server list

deploy/products.js

/* * Define multiple server accounts and export the current environment server account */ based on the SERVER_ID
const SERVER_LIST = [
  {
    id: 0.name: 'A- Test Environment '.host: 'xxx.xxx.xxx.xxx'.// ip
    port: 22./ / port
    username: 'root'.// Account for logging in to the server
    password: 'root'.// Account for logging in to the server
    path: 'xxx/xxx/xxx'.// Publish the project path to the static server
    del: ['/var/www/jx/admin/js'.'/var/www/jx/admin/css'] // Delete those that cannot be replaced
  },
  {
    id: 1.name: 'B- Build environment '.host: 'xxx.xxx.xxx.xxx'.// ip
    port: 22./ / port
    username: 'root'.// Account for logging in to the server
    password: 'root'.// Account for logging in to the server
    path: 'xxx/xxx/xxx'.// Publish the project path to the static server
    del: ['/var/www/jx/admin/js'.'/var/www/jx/admin/css'] // Delete those that cannot be replaced},];module.exports = SERVER_LIST;
Copy the code

3 Create an SCP2 automatic deployment script

const scpClient = require('scp2');
const ora = require('ora');
const chalk = require('chalk');
const servers = require('./products');
let server = servers[process.env.NODE_ENV === 'prod' ? 1 : 0];
const spinner = ora('Posting to' + (process.env.NODE_ENV === 'prod' ? 'production' : 'test') + 'Server... ');

var Client = require('ssh2').Client;

var conn = new Client();
conn
  .on('ready'.function() {
    // rm delete dist file, \n is newline, execute restart nginx command
    let dels = ""
    server.del.forEach(item= > {
        dels += `rm -rf ${item}\n`;
    });
    conn.exec(dels, function (err, stream) {
      if (err) throw err;
      stream
        .on('close'.function(code, signal) {
          // After executing shell command, put the start upload deployment project code in this
            spinner.start();
            scpClient.scp(
            'dist/',
            {
                host: server.host,
                port: server.port,
                username: server.username,
                password: server.password,
                path: server.path
            },
            function (err) {
                spinner.stop();
                if (err) {
                    console.log(chalk.red('Publishing failed.\n'));
                    throw err;
                } else {
                    console.log(chalk.green('Success! Successfully published to ' + (process.env.NODE_ENV === 'prod' ? 'production' : 'test') + 'Server! \n')); }}); conn.end(); }) .on('data'.function (data) {
            console.log('STDOUT: ' + data);
        })
        .stderr.on('data'.function (data) {
            console.log('STDERR: ' + data);
        });
    });
    })
    .connect({
        host: server.host,
        port: server.port,
        username: server.username,
        password: server.password
    });
Copy the code

4 Add Instructions

Add directives to package.json

"upload-test": "NODE_ENV=test node ./deploy"."upload-prod": "NODE_ENV=prod node ./deploy"
Copy the code

5 Use Instructions

Release test environment

npm run upload-test
Copy the code

12 Automatically create a node page

Every time I need to write the general structure of VUE, I think it is a more troublesome thing. It’s generally possible to create new ones using vscode, but I think node is more convenient

1 Configure your template

generateTpl.js

Install personal habit can write multiple templates here, we will only demonstrate one

exports.table = function(pageName) {

var tpl = `<template>
  <basic-container>
    <h3>${pageName}-page</h3>
  </basic-container>
</template>

<script>

export default {
  data() {
    return {
      
    };
  },
  methods: {
  }
};
</script>

<style scoped>
</style>
`
return tpl;
}
Copy the code

2 install the inquirer

npm install inquirer –save-dev

3 Create an automatic creation script

var path = require('path');
var fs = require('fs');
var generateTpl = require('./generateTpl');
var inquirer = require('inquirer')

const createPage = {
    template: "table".init: function() {
        const promptName = [{
            type: 'input'.message: 'Template name'.name: 'templateName'.filter: function (val) {
                return val.toLowerCase()
            }
        }]
        const promptList = [{
            type: 'list'.message: 'Please select a template'.name: 'template'.choices: ['form'.'form'].filter: function (val) {
                return val.toLowerCase()
            }
        }]

        inquirer.prompt(promptName).then(name= > {
            inquirer.prompt(promptList).then(anwsers= > {
                this.initParams(name.templateName);
                if (anwsers.template==='form') {
                    this.template = "table"
                }else{
                    this.template = "form"
                }
                this.getAllPage();
                this.generatePage(); })})},initParams: function (templateName) {
        
        this.pageName = templateName;

        this.pageDir = path.join(__dirname, '.. /src/views');

        this.allPages = ""

    },
    getAllPage: function() {

        this.allPages = fs.readdirSync(this.pageDir);

    },
    generatePage: function(){

        if(this.allPages.indexOf(this.pageName) == - 1) {
            
            this.toGenerageDir();
        } else {

            console.error('Current page already exists'); }},toGenerageDir: function(){
        
        try{
            
            fs.mkdir(path.join(this.pageDir, this.pageName), function(err){

                if(err){

                    console.error(err);
                    return;
                }

                this.toGenerateFiles();

                console.log('Page created');

            }.bind(this));
        }catch(e){

            console.error(e); }},toGenerateFiles: function() {
        
        // Select the template
        var vueFile = path.join(this.pageDir, this.pageName, `index.vue`);
        var imageDir = path.join(this.pageDir, this.pageName, 'images')
		
        // Create a file
        fs.writeFileSync(vueFile, generateTpl[this.template](this.pageName));
        fs.mkdirSync(imageDir)
    }
}

createPage.init();
Copy the code

3 Add Instructions

Add directives to package.json

 "create-page": "node create-page/create-page.js".Copy the code

4 Use Instructions

npm run create-page
Copy the code