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:
development
Pattern is used tovue-cli-service serve
production
Pattern is used tovue-cli-service build
和vue-cli-service test:e2e
test
Pattern 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