If you can sit through this conversation, you might want to get your hands on a code generator, and your coding life might get a little bit easier.

Start with a scaffolding

Daniel: I’m going to start a code generator, one that can generate project code quickly. What do you recommend?

Mr. Egg: I’ve been using Yeoman, an open source project that is fast surpassing 10K Star. Today, however, it’s not Yeoman, but ncgen, a new breed of young meat that may be more approachable.

Daniel: I really like simple ones. How can I use this one?

Mr. Egg: As always, you say what you want, and I try to answer them all

First, you need a project template

Daniel: I have a project template (for example: vue3-NCgen-demo) and I want all new projects to come from this project template, so I just need to focus on maintaining this project template.

Mr. Egg: OK, that’s what project scaffolding is for. Let’s take a look at how NCgen handles it.

Step 1 Install NCGen

$ npm i ncgen -g # yarn global add ncgen
Copy the code

The second step generates the ncgen-config.js configuration file, which describes the logic of the code generator

$ ncgen genConf
Copy the code

Step 3 Change main.tmplSource in ncgen-config.js to the address of the project template.

export default {
  main: {
    tmplSource: "https://github.com/daniel-dx/vue3-ncgen-demo.git",}};Copy the code

Run it:

ncgen ncgen-config.js
Copy the code

Simple copy is not enough, minor modifications are the norm

Daniel: Oh, that’s good. However, the generated project is exactly the same as the project template, but it always has its own different information from the project template, such as project name, author name, etc. I don’t want to have to manually modify this every time I build a project.

Mr. Egg: OK, very reasonable request. Since this information is provided by the person who created the project, we need to collect this information through questions, and then make changes to the generated project based on this information. Let’s modify main.prompt and main.updateFiles in ncgen-config.js

Example: Replace the string in the package.json file in the generated project as follows: replace the vue3-ncgen-demo string with the project name entered by the user; replace the daniel.xiao string with the author name entered by the user

export default {
  main: {
    prompt: [{type: "input".name: "author".message: "What is the author's name",},],...updateFiles: {
      "package.json": function (content, options) {
        const answers = this.$answers
        return api.replace(content, {
          "vue3-ncgen-demo": answers.projectNameObj.kebabCase,
          "Daniel.xiao": answers.author, }); ,}}}};Copy the code

Daniel: Gee, I notice that instead of using a template engine, I use string substitution

Mr. Egg: Yes, the design makes a lot of sense. Replacing files with a template engine may cause the project template itself to fail because the template engine requires placeholders, which can cause code parsing errors

Daniel: Yeah, so the project template is just a normal project, and you don’t have to change the placeholder of the template

Extra files handled yesterday? Please delete

Daniel: I’ll go on. I have some template directories and files in my project templates (module template directories, component template files), but I don’t want to see them in the generated project.

Mr. Egg: OK, no problem, just need to delete the specified files and directories. Let’s modify the main.removeFiles in ncgen-config.js.

Example: delete the generated in the project ncgen – config. Js and SRC/components/base/Template vue file

export default {
  main: {
    removeFiles: ["ncgen-config.js"."src/components/base/Template.vue"],}};Copy the code

One-stop service: automatic installation dependency

Daniel: I just noticed that the above example automatically installs dependencies at runtime. It should be installed using NPM. Does this support YARN? Can I do that if I am a non-NodeJS project like Python, Go, etc.?

Mr. Egghead: Well, yes, the generated ncgen-config.js uses NPM I by default to install dependencies, see the example below. If you want to change to YARN, simply change command to YARN Install. For Python, Go, and other languages, simply change command to the corresponding dependency installation command

export default {
  main: {
    installDependencies: {
      skip: false.tips: "Dependencies are being installed, it may take a few minutes".command: "npm i",}}};Copy the code

Finally, a friendly reminder

Daniel: Great, the scaffolding is just a few clicks away. I think it needs a friendly welcome and a nice ending

Mr. Egghead: As you wish, simply modify main.welcome and main.complete

export default {
  main: {
    welcome: "Welcome to use (Vue 3 + TypeScript + Vite) project generator".complete: "Congratulations, the operation is successful",}};Copy the code

Hf is not using scaffolding

Daniel: The scaffolding is done, but it is only used for new projects. It is also a part of code addition, such as adding a function module, adding a component, adding an API, etc

Mr. Egg: I know what you mean. Same old rule. You ask me questions

Code templates exist in project templates

Daniel: I’m adding a new component to a project. I don’t want to copy an existing component and make all sorts of changes to remove code. In fact, the project template contains the component’s code template

Mr. Egg: OK. We’ll start by adding a subcommand called add-component to ncgen-config.js.

Example Description (assuming the value of category and name are ‘busi’ and ‘demo’ respectively) : Description describes the function of the subcommand. ListDirs is an API that is useful for letting users choose where to insert code. AddFilesTo configuration will project Template in SRC/components/base/Template. The vue inserted into the project in the SRC/components/busi/Demo. Vue file.

export default {
  sub: {
    "add-component": {
      description: "Add vue component".prompt: [{type: "list".choices: function () {
            return api.listDirs("src/components/");
          },
          name: "category".message: "Please select the category"}, {type: "input".name: "name".message: "What is the component name".validate(input) {
            if(! input)return "The component name is required";
            return true; }},].tmplSource: "https://github.com/daniel-dx/vue3-ncgen-demo.git".addFilesTo: function () {
        const answers = this.$answers;
        return {
          "src/components/base/Template.vue": `src/components/${answers.category}/${answers.nameObj.upperFirstCamelCase}.vue`}; }},}};Copy the code

The code template does not exist in the project template

Daniel: Beautiful. But for existing projects that are not from the project template, I also want to add some subcommands to generate some code for the project.

Mr. Egg: Subcommands support two ways to add files, one is the code template from the project template mentioned above, and the other is the one you create on the fly. Both can be used simultaneously. The following example shows how to create code files on the fly

Example (assuming the category and the name of the value of the ‘busi’ and ‘demo’) respectively: addFiles configuration will be created in the project of the SRC/components/busi/demo. The md file, the contents of this file to # demo

export default {
  sub: {
    "add-component": {
      addFiles: function () {
        const answers = this.$answers;
        return{[`src/components/${answers.category}/${answers.nameObj.upperFirstCamelCase}.md`] :function () {
            return ` #${answers.nameObj.upperFirstCamelCase}`; }}; }},}};Copy the code

Recommended replacement techniques for wall cracks

Daniel: After that, some changes are made to the content of the file (for example, when the page is added, the routing rule file will be automatically modified to register the route for the page), which is the same operation as the main command.

Mr. Egg: Very clever. A recommended tip is to add some identifying comments where snippets of code need to be inserted, as shown in the SRC/app.vue code:

<template> <img alt="Vue logo" src="./assets/logo.png" /> <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" /> <! -- Don't touch me - place component --> </template> <script lang="ts"> import { defineComponent } from 'vue' import HelloWorld from './components/busi/HelloWorld.vue' // <! -- Don't touch me - import component --> export default defineComponent({ name: 'App', components: { HelloWorld, // <! -- Don't touch me - register component --> } }) </script>Copy the code

InsertBefore this API inserts the specified content before the specified match location of the file

export default {
  sub: {
    updateFiles: function () {
      const answers = this.$answers;
      return {
        "src/App.vue": function (content, options) {
          return api.insertBefore(content, {
            "/ / <! -- Don't touch me - import component -->": `import ${answers.nameObj.upperFirstCamelCase} from './components/${answers.category}/${answers.nameObj.upperFirstCamelCase}.vue'`."/ / <! -- Don't touch me - register component -->": `${answers.nameObj.upperFirstCamelCase}, `."<! -- Don't touch me - place component -->": ` <${answers.nameObj.upperFirstCamelCase}/ > `}); },`src/components/${answers.category}/${answers.nameObj.upperFirstCamelCase}.vue`] :function (content, options) {
          return api.replace(content, {
            Template: `${answers.nameObj.upperFirstCamelCase}`}); }}; ,}}};Copy the code

Daniel: Perfect. Thanks, dude. I feel like I’ve got my head in the game, and I’m ready to try my first code generator

Mr. Egg: Thank you. I look forward to your feedback

Write in the last

Above – complete configuration

You can view the full configuration of ncgen-config.js in the example: github.com/daniel-dx/v…

Below – ncGen website


Keywords: NCgen, scaffolding, Generator, code generator, scaffolding