80

vue-cil 3.0 配置说明

 4 years ago
source link: https://juejin.im/post/5d130b9a518825670124a721
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
2019年06月26日 阅读 15252

vue-cil 3.0 配置说明

1 安装vue-cli3.0

0 淘宝镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org
复制代码

1 安装vue-cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli
复制代码

2 查看版本

vue --version
复制代码

3 vue-cli构建项目

vue create vue-demo
复制代码


image.png

选择默认即可、可起服务

4 目录结构

├── README.md  					# 说明
|-- dist                       	# 打包后文件夹
├── babel.config.js 			# babel语法编译
├── package-lock.json 
├── package.json
├── public						# 静态文件夹
│   ├── favicon.ico
│   └── index.html				#入口页面
└── src						    # 源码目录
    ├── App.vue - 页面
    ├── assets  - 静态目录
    │   └── logo.png
    ├── components 组件
    │   └── HelloWorld.vue
    └── main.js                  # 入口文件,加载公共组件
|-- vue.config.js                # 配置文件 
|-- .eslintrc.js    		  	# ES-lint校验                   
|-- .gitignore          		# git忽略上传的文件格式   
|-- babel.config.js   			# babel语法编译                        
|-- package.json       	     # 项目基本信息 
复制代码

标准的vue目录结构

2 环境变量和模式

在npm下实际上vue-cli  启动的时候,已经确定了环境变量与模式,这样方便代码的构建

打开package.json后

image.png

我们这边描述的环境就在scripts中

是 Vue CLI 项目中一个重要的概念。默认情况下,一个 Vue CLI 项目有三个模式:

  • development 模式用于 vue-cli-service serve
  • production 模式用于 vue-cli-service build 和 vue-cli-service test:e2e
  • test 模式用于 vue-cli-service test:unit

你可以通过传递 --mode 选项参数为命令行覆写默认的模式。例如,如果你想要在构建命令中使用开发环境变量,请在你的 package.json 脚本中加入

``` "dev-build": "vue-cli-service build --mode development", ```

那么我们在代码里面怎么调用呢、和他的应用场景呢

process.env.NODE_ENV
复制代码

这样我们就可以获取他的环境变量

我们在src目录下新建一个config
构建一个env.js的目录

let baseUrl = '';

const env = process.env
if (env.NODE_ENV == 'development') {
    baseUrl = `http://192.168.1.1`; // 开发环境地址
} else if (env.NODE_ENV == 'production') {
    baseUrl = `http://192.168.1.2`; //生产环境地址
} else if (env.NODE_ENV == 'test') {
    baseUrl = `http://192.168.1.3`; //测试环境地址
}

export {
    baseUrl,
    env
}
复制代码

那么这样我们就可以直接使用不同环境下的

3 IE兼容处理、移除console

npm install @babel/polyfill -s

npm install babel-plugin-transform-remove-console -s
复制代码

在babel.config.js中配置如下


const plugins = []
if (process.env.NODE_ENV === 'production') {
  // 移除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
}
复制代码

4 vue-cli 基本配置

新建一个vue.config.js的文件夹,开始可配置vue-cli

module.exports = {
    //部署应用包时的基本 URL
    publicPath: process.env.NODE_ENV === 'production' ? '/online/' : './',
    //当运行 vue-cli-service build 时生成的生产环境构建文件的目录
    outputDir: 'dist',
    //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
    assetsDir: 'assets',
    // eslint-loader 是否在保存的时候检查 安装@vue/cli-plugin-eslint有效
    lintOnSave: true,
    //是否使用包含运行时编译器的 Vue 构建版本。设置true后你就可以在使用template
    runtimeCompiler: true,
    // 生产环境是否生成 sourceMap 文件 sourceMap的详解请看末尾  
    productionSourceMap: false,

}
复制代码

5 添加别名

新建一个vue.config.js的文件夹,开始可配置vue-cli

1 别名配置

const path =  require('path'); //引入path模块(node)
const resolve = (dir) => path.join(__dirname, dir); //将文件组成绝对路径
 
module.exports = {
    chainWebpack: config => {
        // 添加别名
        config.resolve.alias
          .set('@', resolve('src'))
          .set('assets', resolve('src/assets'))
          .set('components', resolve('src/components'))
    }
}
复制代码

2 运用场景

目录的结构可能层层叠叠,后在达到目录

例如: 刚刚的env.js目录

import {baseUrl} from '../config/env'
复制代码

但是我们不一定保证,目录就那么靠近,那么怎么处理

// @代表src目录下,即可这样调用

import {baseUrl} from '@/config/env'
复制代码

7 优化-配置externals

防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖

### 项目中的使用 > 一般性vue项目,我们都会把一些框架包,给抽离出来。例如:

  • ELEMENT
  • VueRouter
  • axios

1 引入框架

我们把一些外包引用的包,提取出来,放在public中

1

2 编辑 externals

我们在vue.config.

module.exports = {

   configureWebpack: config => {

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

   }
复制代码

3 引入cdn

那么这时候我们需要在  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" content="width=device-width,initial-scale=1.0,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.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.css">
    <title>vue-demo</title>
  </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>
    <!-- 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/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-ui/2.5.4/index.js" charset="utf-8"></script>
  </body>

</html>
复制代码

8 优化-开启Gzip 压缩

vue cli 3.0相比2.0有不少的改动,最明显的就是 build文件夹不见了,改为根目录的vue.config.js
在此记录一下Gzip配置的过程

npm i -D compression-webpack-plugin
复制代码

2 修改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/, //匹配文件名
                        threshold: 10240,//对超过10k的数据压缩
                        deleteOriginalAssets: false //不删除源文件
                    })
                ]
            }
        }
    },
}
复制代码

3 nginx配置gzip

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;
复制代码

第1行:开启Gzip

第2行:不压缩临界值,大于1K的才压缩,一般不用改

第3行:buffer,就是,嗯,算了不解释了,不用改

第4行:用了反向代理的话,末端通信是HTTP/1.0,有需求的应该也不用看我这科普文了;有这句的话注释了就行> 了,默认是HTTP/1.1

第5行:压缩级别,1-10,数字越大压缩的越好,时间也越长,看心情随便改吧

第6行:进行压缩的文件类型,缺啥补啥就行了,JavaScript有两种写法,最好都写上吧,总有人抱怨js文件没有压> 缩,其实多写一种格式就行了

第7行:跟Squid等缓存服务有关,on的话会在Header里增加"Vary: Accept-Encoding",我不需要这玩意,自己> 对照情况看着办吧

第8行:IE6对Gzip不怎么友好,不给它Gzip了

9 优化-首屏加载

<!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" content="width=device-width,initial-scale=1.0,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.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.css">
    <title>vue-demo</title>
    
   <style>
     html,
     body,
     #app {
       height: 100%;
       margin: 0px;
       padding: 0px;
     }

     .chromeframe {
       margin: 0.2em 0;
       background: #ccc;
       color: #000;
       padding: 0.2em 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.5s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -o-animation: spin 1.5s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -ms-animation: spin 1.5s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       -webkit-animation: spin 1.5s linear infinite;
       /* Chrome, Opera 15+, Safari 5+ */
       animation: spin 1.5s 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.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
       transition: all 0.7s 0.3s 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.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
       transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
     }

     .loaded #loader {
       opacity: 0;
       -webkit-transition: all 0.3s ease-out;
       transition: all 0.3s 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.3s 1s ease-out;
       transition: all 0.3s 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,请耐心等待
          <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/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-ui/2.5.4/index.js" charset="utf-8"></script>
  </body>

</html>

复制代码


image.png

10 预处理器 (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
复制代码
然后你就可以导入相应的文件类型,或在 *.vue 文件中这样来使用:

<style scoped lang="stylus">
.personal
  position relative
  .banner-red
    width 100%
    height 100px
</style>
复制代码

11 node自动化部署

1 安装scp2

npm install scp2 --save-dev
复制代码

2 配置一个服务器列表

deploy/products.js

image.png
/*
 *定义多个服务器账号 及 根据 SERVER_ID 导出当前环境服务器账号
 */
const SERVER_LIST = [
  {
    id: 0,
    name: 'A-测试环境',
    host: 'xxx.xxx.xxx.xxx', // ip
    port: 22,// 端口
    username: 'root', // 登录服务器的账号
    password: 'root', // 登录服务器的账号
    path: 'xxx/xxx/xxx', // 发布至静态服务器的项目路径
    del: ['/var/www/jx/admin/js', '/var/www/jx/admin/css'] // 删除这些无法替换的
  },
  {
    id: 1,
    name: 'B-生成环境',
    host: 'xxx.xxx.xxx.xxx', // ip
    port: 22,// 端口
    username: 'root', // 登录服务器的账号
    password: 'root', // 登录服务器的账号
    path: 'xxx/xxx/xxx', // 发布至静态服务器的项目路径
    del: ['/var/www/jx/admin/js', '/var/www/jx/admin/css'] // 删除这些无法替换的
  },
];

module.exports = SERVER_LIST;
复制代码

3 创建scp2自动化部署脚本

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('正在发布到' + (process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器...');

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

var conn = new Client();
conn
  .on('ready', function() {
    // rm 删除dist文件,\n 是换行 换行执行 重启nginx命令 我这里是用docker重启nginx
    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) {
          // 在执行shell命令后,把开始上传部署项目代码放到这里面
            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('发布失败.\n'));
                    throw err;
                } else {
                    console.log(chalk.green('Success! 成功发布到' + (process.env.NODE_ENV === 'prod' ? '生产' : '测试') + '服务器! \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
    });
复制代码

4 添加指令

在 package.json 中添加指令

"upload-test": "NODE_ENV=test node ./deploy",
"upload-prod": "NODE_ENV=prod node ./deploy"
复制代码

5 使用指令

发布测试环境

npm run upload-test
复制代码

12 node自动化新建页面

每一次都需要需要写vue的大致构造,我觉得还是比较麻烦的一件事。一般性可以使用vscode新建,但是我认为node更加方便

1 配置属于你的模板

image.png

generateTpl.js

安装个人习惯可以写多个模板这里,我们只演示一种

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;
}
复制代码

2 安装 inquirer

npm install inquirer --save-dev

3 创建自动化新建脚本

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: '模板的名称',
            name: 'templateName',
            filter: function (val) {
                return val.toLowerCase()
            }
        }]
        const promptList = [{
            type: 'list',
            message: '请选择一种模版',
            name: 'template',
            choices: ['表格', '表单'],
            filter: function (val) {
                return val.toLowerCase()
            }
        }]

        inquirer.prompt(promptName).then(name => {
            inquirer.prompt(promptList).then(anwsers => {
                this.initParams(name.templateName);
                if (anwsers.template==='表格') {
                    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('当前页面已经存在了');
        }
    },
    toGenerageDir: function(){
        
        try{
            
            fs.mkdir(path.join(this.pageDir, this.pageName), function(err){

                if(err){

                    console.error(err);
                    return;
                }

                this.toGenerateFiles();

                console.log('页面创建完成');

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

            console.error(e);
        }
    },
    toGenerateFiles: function() {
        
        // 选择模板
        var vueFile = path.join(this.pageDir, this.pageName, `index.vue`);
        var imageDir = path.join(this.pageDir, this.pageName, 'images')
		
        // 创建文件
        fs.writeFileSync(vueFile, generateTpl[this.template](this.pageName));
        fs.mkdirSync(imageDir)
    }
}

createPage.init();
复制代码

3 添加指令

在 package.json 中添加指令

 "create-page": "node create-page/create-page.js",
复制代码

4 使用指令

npm run create-page
复制代码


image.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK