二、创建脚手架(generator)生成 vue 项目

涂泰平
2023-12-01

3、创建 generator 生成 vue 项目

3.1、generator 生成 package.json

  1. 自选文件夹,创建"文件夹generator-vue"、“文件夹vue-demo” ;

  2. 将上面写好的 “toolchain文件” 中的 “generators 文件夹”、“package.json 文件” 两个文件转移到 “generator-vue文件夹” 中;

  3. 在 “generator-vue/generators/app/index.js” 文件中,为生成 “vue-demo” 项目的 “package.json” 文件,而作配置:

    var Generator = require('yeoman-generator');
    
    module.exports = class extends Generator {
        constructor(args, opts) {
            super(args, opts);
        }
    
        // 为项目创建 package.json
        async initPackage() {
            // 询问后创建项目名称,默认为项目文件夹名称;
            let answers = await this.prompt(
                {
                    type: "input",
                    name: "name",
                    message: "Your project name",
                    default: this.appname// 默认为项目文件夹名称
                }
            );
            const pkgJson = {
                "name": answers.name,
                "version": "1.0.0",
                "description": "",
                "main": "generators/app/index.js",
                "scripts": {
                    "test": "echo \"Error: no test specified\" && exit 1"
                },
                "author": "",
                "license": "ISC",
                "devDependencies": {
                },
                "dependencies": {
                }
            };
    
            // Extend or create package.json file in destination path
            this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
        }
    
        // 为项目安装预备依赖到不同环境;
        install() {
            this.npmInstall(["vue"], {"save-dev": false});
            this.npmInstall(["webpack", "vue-loader"], {"save-dev": true});
        }
      
      	// 为项目增加“HelloWord.vue”模版文件;
        copyFiles() {
            this.fs.copyTpl(
                this.templatePath('HelloWord.vue'),
                this.destinationPath('src/HelloWord.vue'),
                {}
            );
        }
    };
    
  4. “generator-vue空文件夹” 下 cd 命令行,键入npm link;

  5. “vue-demo文件夹” 下 cd 命令行,键入yo vue,“vue-demo文件夹” 内新增3个文件:

    1. packag.json 文件
    2. package-lock.json 文件
    3. node-moudles 文件夹

3.2、generator 生成 vue 模板

  1. 在 “generator-vue/generators/app/templates” 文件中,增加 js 模版文件 “HelloWord.vue” 如下:

    <template>
      <p>{{ greeting }} World!</p>
    </template>
    
    <script>
    module.exports = {
      data: function() {
        return {
          greeting: "Hello"
        };
      }
    };
    </script>
    
    <style scoped>
    p {
      font-size: 2em;
      text-align: center;
    }
    </style>
    
  2. 在 “generator-vue/generators/app/index.js” 文件 ”Generator“ 类中,创建 “copyFiles()” ,为生成 vue 模板做配置:

    var Generator = require('yeoman-generator');
    
    module.exports = class extends Generator {
        constructor(args, opts) {
            // …………
        }
    
        // 为项目创建 package.json
        async initPackage() {
          	// …………
        }
    
        // 为项目安装预备依赖到不同环境;
        install() {
          	// …………
        }
      
      	// 为项目增加“HelloWord.vue”模版文件;
        copyFiles() {
            this.fs.copyTpl(
                this.templatePath('HelloWord.vue'),
                this.destinationPath('src/HelloWord.vue'),
                {}
            );
        }
    };
    
  3. “vue-demo文件夹” 下 cd 命令行,键入yo vue,“vue-demo文件夹” 内变为4个文件:

    1. packag.json 文件
    2. package-lock.json 文件
    3. node-moudles 文件夹
    4. src 文件夹
      • HelloWord.vue 文件

3.3、generator 生成 webpack.config.js

  1. 在 “generator-vue/generators/app/templates” 文件中,增加 webpack 模版文件 “webpack.config.js” 如下:

    const { VueLoaderPlugin } = require('vue-loader')
    const webpack = require('webpack'); // 用于访问内置插件
    
    module.exports = {
        entry: "./src/main.js",
        mode: "development",
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                },
                // 它会应用到普通的 `.js` 文件
                // 以及 `.vue` 文件中的 `<script>` 块
                // {
                //     test: /\.js$/,
                //     loader: 'babel-loader'
                // },
                // 它会应用到普通的 `.css` 文件
                // 以及 `.vue` 文件中的 `<style>` 块
                {
                    test: /\.css$/,
                    use: [
                        'vue-style-loader',
                        'css-loader'
                    ]
                }
            ]
        },
        plugins: [
            // 请确保引入这个插件来施展魔法
            new VueLoaderPlugin()
        ]
    }
    
  2. 在 “generator-vue/generators/app/templates” 文件中,增加 main.js 模版文件 “main.js” 如下:

    import HelloWord from "./HelloWord.vue";
    
  3. 为使在 “vue-demo 文件” 下可以成功npm run build使用 webpack 打包,在 “generator-vue/generators/app/index.js” 文件的 ”Generator“ 类中增加配置如下++++add+++++:

    var Generator = require('yeoman-generator');
    
    module.exports = class extends Generator {
        constructor(args, opts) {
            // …………
        }
    
        // 为项目创建 package.json
        async initPackage() {
            // 询问后创建项目名称,默认为项目文件夹名称;
            let answers = await this.prompt(
                // …………
            );
            const pkgJson = {
                // …………
                "scripts": {
                    "test": "echo \"Error: no test specified\" && exit 1",
                  	// +++++add+++++
                    "build": "webpack --config webpack.config.js"
                },
                // …………
            };
                // …………
        }
    
        // 为项目安装预备依赖到不同环境;
        install() {
            this.npmInstall(["vue"], {"save-dev": false});
          	// +++++add+++++
            this.npmInstall([
                "webpack",
                "webpack-cli",
                "vue-loader",
                "vue-template-compiler",
                "vue-style-loader",
                "css-loader",
            ], {"save-dev": true});
        }
    
        // 为项目增加模版文件;
        copyFiles() {
            this.fs.copyTpl(
                this.templatePath('HelloWord.vue'),
                this.destinationPath('src/HelloWord.vue'),
                {}
            );
          	// +++++add+++++
            this.fs.copyTpl(
                this.templatePath('webpack.config.js'),
                this.destinationPath('webpack.config.js'),
                {}
            );
    	      // +++++add+++++
            this.fs.copyTpl(
                this.templatePath('main.js'),
                this.destinationPath('src/main.js'),
                {}
            );
        }
    };
    
  4. “vue-demo文件夹” 下 cd 命令行,键入yo vue,“vue-demo文件夹” 内变为4个文件:

    1. packag.json 文件
    2. package-lock.json 文件
    3. node-moudles 文件夹
    4. webpack.config.js 文件
    5. src 文件夹
      • HelloWord.vue 文件
      • main.js 文件
  5. “vue-demo文件夹” 下 cd 命令行,键入npm run build,“vue-demo文件夹” 内增加 webpack 打包后的 “dist 文件夹/main.js 文件”,使用webpack 打包成功;

3.4、generator 生成 scr/index.html

  1. 在 “generator-vue/generators/app/templates” 文件中,增加 html 模版文件 “index.html” 如下(全文件展示):

    <html>
    
    <head>
      <title>
        <%= title %>
      </title>
    </head>
    
    <body>
      <div id="app"></div>
      <!-- script 放到 div 之后,否则会找不到 #app 元素 -->
      <script src="./main.js"></script>
    </body>
    
    </html>
    
  2. 在 “generator-vue/generators/app/templates/main.js” 文件中,修改 “main.js” 如下(全文件展示,看//+++++add++++++):

    import HelloWord from "./HelloWord.vue";
    //+++++add++++++
    import Vue from "Vue";
    //+++++add++++++
    new Vue({
        el: "#app",
        render: h => h(HelloWord)
    });
    
  3. 在 “generator-vue/generators/app/index.js” 文件中,增加如下配置(全文件展示,看//+++++add++++++):

    var Generator = require('yeoman-generator');
    
    module.exports = class extends Generator {
        constructor(args, opts) {
            super(args, opts);
        }
    
        // 为项目创建 package.json
        async initPackage() {
            // 询问后创建项目名称,默认为项目文件夹名称;
          	// +++++add:修改为 this.anwsers方便 copyFiles 中 title 引用+++++ 
            this.answers = await this.prompt(
                {
                    type: "input",
                    name: "name",
                    message: "Your project name",
                    default: this.appname// 默认为项目文件夹名称
                }
            );
            const pkgJson = {
                "name": this.answers.name,
                "version": "1.0.0",
                "description": "",
                "main": "generators/app/index.js",
                "scripts": {
                    "test": "echo \"Error: no test specified\" && exit 1",
                    "build": "webpack --config webpack.config.js"
                },
                "author": "",
                "license": "ISC",
                "devDependencies": {
                },
                "dependencies": {
                }
            };
    
            // Extend or create package.json file in destination path
            this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
        }
    
        // 为项目安装预备依赖到不同环境;
        install() {
            this.npmInstall(["vue"], {"save-dev": false});
            this.npmInstall([
                "webpack",
                "webpack-cli",
                "vue-loader",
                "vue-template-compiler",
                "vue-style-loader",
                "css-loader",
              	// +++++add+++++
                "copy-webpack-plugin"
            ], {"save-dev": true});
        }
    
        // 为项目增加模版文件;
        copyFiles() {
            this.fs.copyTpl(
                this.templatePath('HelloWord.vue'),
                this.destinationPath('src/HelloWord.vue'),
                {}
            );
            this.fs.copyTpl(
                this.templatePath('webpack.config.js'),
                this.destinationPath('webpack.config.js'),
                {}
            );
            this.fs.copyTpl(
                this.templatePath('main.js'),
                this.destinationPath('src/main.js'),
                {}
            );
          	// +++++add+++++
            this.fs.copyTpl(
                this.templatePath('index.html'),
                this.destinationPath('src/index.html'),
                {title: this.answers.name}
            );
        }
    };
    
  4. 在 “generator-vue/generators/app/templates/webpack.config.js” 文件中,增加如下配置(全文件展示,看//+++++add++++++):

    const { VueLoaderPlugin } = require('vue-loader')
    const CopyPlugin = require("copy-webpack-plugin");
    const webpack = require('webpack'); // 用于访问内置插件
    
    module.exports = {
        entry: "./src/main.js",
        mode: "development",
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                },
                {
                    test: /\.css$/,
                    use: [
                        'vue-style-loader',
                        'css-loader'
                    ]
                }
            ]
        },
        plugins: [
            // 请确保引入这个插件来施展魔法
            new VueLoaderPlugin(),
          	//+++++add++++++
            new CopyPlugin({
                patterns: [
                    { from: "src/*.html", to: "[name][ext]" }
                ],
            }),
        ]
    }
    
  5. “vue-demo文件夹” 下 cd 命令行,键入yo vue,“vue-demo项目” 创建成功;

  6. “vue-demo文件夹” 下 cd 命令行,键入npm run build,“vue-demo项目” 打包完成;

    • 点开 “vue-demo文件夹/dist文件夹/index.html” 如下图展示:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HGZ2Jc0J-1617232616620)(https://raw.githubusercontent.com/FreeWisdom/Frontend-07-Template/main/Week17/img/HelloWord.png “Hello Word!”)]

3.5、”创建脚手架—>生成项目“总结

​ 通过引用 “yeoman-generator” 创建 Generator 类。Generator 类使用 webpack 、vue loader、copy-webpack-plugin 等通用工具,对 packag.json模板、xxx.vue模板、main.js模板、index.html模板、webpack.config.js模板进行模板设计。从而实现了一个 vue.js 脚手架(generator),通过命令yo vue即可创建一个 vue.js 项目后进行开发。

 类似资料: