Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of Vue-cli principle

2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/03 Report--

Background

In peacetime work will encounter a lot of Mini Program customized with the same template, so want to build a scaffolding tool to generate templates, template-based construction of the corresponding Mini Program, and usually Mini Program is written using the mpvue framework, so first refer to the principles of Vue-cli. After knowing the principle, customizing your own template scaffolding will certainly get twice the result with half the effort.

Before we talk about the code, let's review the use of Vue-cli. We usually use the webpack template package and enter the following code.

Vue init webpack [project-name] copy code

After executing this code, the system automatically downloads the template package, and then asks us some questions, such as the name of the template, the author, whether we need to use eslint, using npm or yarn to build, and so on. When we answer all the questions, we start to build the scaffolding project.

We will source code down, the source code warehouse click here, the usual scaffolding is still version 2.0, it should be noted that the default branch is on dev, dev is version 3.0.

Let's first take a look at package.json. There is a passage in the document.

{"bin": {"vue": "bin/vue", "vue-init": "bin/vue-init", "vue-list": "bin/vue-list"}} copy the code

It can be seen that the command vue init we use should come from the file bin/vue-init. Let's take a look at the contents of this file next.

Bin/vue-init

Const download = require ('download-git-repo') const program = require (' commander') const exists = require ('fs'). ExistsSyncconst path = require (' path') const ora = require ('ora') const home = require (' user-home') const tildify = require ('tildify') const chalk = require (' chalk') const inquirer = require ('inquirer') const rm = require (' rimraf'). Syncconst logger = require ('.. / lib/logger') const generate = require ('.. / lib/generate') const checkVersion = require ('.. / lib/check-version') const warnings = require ('.. / lib/warnings') const localPath = require ('.. / lib/local-path') copy code

Download-git-repo A module for downloading a git repository project commander can output text to the terminal fs is a node file read and write module path module provides some tool functions Ora this module is used to display the path of loading animation user-home to get the user's home directory in the terminal, tildify converts the absolute path to the waveform path, for example, / Users/sindresorhus/dev → ~ / dev inquirer is a command line answer module, you can set the terminal's questions yourself. And then give the corresponding treatment to these answers. Rimraf is a module that can use the UNIX command rm-rf, and the rest of the local path modules are actually utility classes, which we'll talk about when we use them.

/ / the method of whether it is a local path is mainly to determine whether there is a `. /` const isLocalPath = localPath.isLocalPath// in the template path. If the path parameter is an absolute path, it is returned directly. If it is relative, copy the code / * Usage according to the current path stitching const getTemplatePath = localPath.getTemplatePath. * / program .usage ('[project-name]') .option ('- c,-- clone', 'use git clone') .option ('-- offline', 'use cached template') / * * Help. * / program.on ('--help', () = > {console.log ('Examples:') console.log () console.log (chalk.gray (' # create a new project with an official template')) console.log ('$vue init webpack my-project') console.log () console.log (chalk.gray ('# create a new project straight from a github template')) console.log ('$vue init username/repo my-project') console.log ()}) / * * Help. * / function help () {program.parse (process.argv) if (program.args.length)

< 1) return program.help()}help()复制代码 这部分代码声明了vue init用法,如果在终端当中 输入 vue init --help或者跟在vue init 后面的参数长度小于1,也会输出下面的描述 Usage: vue-init [project-name] Options: -c, --clone use git clone --offline use cached template -h, --help output usage information Examples: # create a new project with an official template $ vue init webpack my-project # create a new project straight from a github template $ vue init username/repo my-project复制代码 接下来是一些变量的获取 /** * Settings. */// 模板路径let template = program.args[0]const hasSlash = template.indexOf('/') >

-1 const rawName / project name const rawName = program.args [1] const inPlace =! rawName | | rawName = ='.'/ / if no project name or project name input'.' Then name takes the name of the current folder const name = inPlace? Path.relative ('.. /', process.cwd ()): rawName// output path const to = path.resolve (rawName | |'.) / / whether git cloneconst clone = program.clone is needed | | false// tmp is a local template path. If it is offline, then the template path takes the local const tmp = path.join (home,'. Vue-templates', template.replace (/ [\ /:] / g). '-') if (program.offline) {console.log (`> Use cached template at ${chalk.yellow (tildify (tmp))}`) template = tmp} copy code

The next step is to download and produce the template according to the name of the template, and if it is a local template path, it will be generated directly.

/ * Check, download and generate the project. * / function run () {/ / determine whether it is the local template path if (isLocalPath (template)) {/ / get the template address const templatePath = getTemplatePath (template) / / if the local template path exists, start generating the template if (exists (templatePath)) {generate (name, templatePath, to, err = > {if (err) logger.fatal (err) console.log () logger.success ('Generated "% s". Name)})} else {logger.fatal ('Local template "% s" not found.' Template)} else {/ / non-local template path first check whether the version checkVersion (() = > {/ / path contains'/'/ / if not, then enter the logical if (! hasSlash) {/ / splicing path 'vuejs-tempalte' is the official template package const officialTemplate =' vuejs-templates/' + template / / if there is'#'in the path Download if (template.indexOf ('#')! = =-1) {downloadAndGenerate (officialTemplate)} else {/ / if there is no string of-2.0, it will output if (template.indexOf ('- 2.0')! =-1) {warnings.v2SuffixTemplatesDeprecated (template) InPlace?'': name) return} / / download and produce template downloadAndGenerate (officialTemplate)} else {/ / download and generate template downloadAndGenerate (template)})}} copy code

Let's take a look at the downloadAndGenerate method.

/ * Download a generate from a template repo. * * @ param {String} template * / function downloadAndGenerate (template) {/ / execute loading animation const spinner = ora ('downloading template') spinner.start () / / Remove if local template exists / / Delete the locally existing template if (exists (tmp)) rm (tmp) / / template parameter is the destination address tmp is the download address clone parameter represents whether clone download (template, tmp, {clone}) is required Err = > {/ / end loading animation spinner.stop () / / if there is an error in downloading, output log if (err) logger.fatal ('Failed to download repo' + template +':'+ err.message.trim ()) / / enter the production template method after the template has been downloaded successfully. Here we will further talk about generate (name, tmp, to). Err = > {if (err) logger.fatal (err) console.log () logger.success ('Generated "% s"., name)})} copy the code

So far, bin/vue-init is done, and one of the main things this file does is to download and generate the template according to the name of the template, but the specific method of downloading and generating the template is not in it.

Download template

The download method used to download the template belongs to the download-git-repo module.

The most basic usage is as follows. The parameters here are easy to understand. The first parameter is the warehouse address, the second is the output address, the third is whether git clone is required, and four are callback parameters.

Download ('flipxfx/download-git-repo-fixture',' test/tmp', {clone: true}, function (err) {console.log (err?) 'Error':' Success')}) copy the code

In the above run method, it is mentioned that the string of # is actually the use of the download branch module of this module.

Download ('bitbucket:flipxfx/download-git-repo-fixture#my-branch',' test/tmp', {clone: true}, function (err) {console.log (err?) 'Error':' Success')}) copy the code

Generate template

The template generation generate method is in generate.js. Let's take a look at it again.

Generate.js

Const chalk = require ('chalk') const Metalsmith = require (' metalsmith') const Handlebars = require ('handlebars') const async = require (' async') const render = require ('consolidate'). Handlebars.renderconst path = require (' path') const multimatch = require ('multimatch') const getOptions = require ('. / options') const ask = require ('. / ask') const filter = require ('. / filter') const logger = require ('. / logger') copy code

Chalk is a module that allows terminal output to change color. Metalsmith is a generation library for static websites (blogs, projects). Handlerbars is a template compiler that outputs an html async asynchronous processing module through template and json, somewhat similar to turning the method into a threaded consolidate template engine integration library multimatch, a string array matching library options is a self-defined configuration item file.

Two renderers are then registered, similar to conditional rendering of vif velse in vue

/ / register handlebars helperHandlebars.registerHelper ('if_eq', function (a, b, opts) {return a = = b? Opts.fn (this): opts.inverse (this)}) Handlebars.registerHelper ('unless_eq', function (a, b, opts) {return a = = b? Opts.inverse (this): opts.fn (this)}) copy the code

Next, let's look at the key generate method.

Module.exports = function generate (name, src, dest, done) {/ / read the configuration file information in the src directory At the same time, assign name auther (current git user) to opts const opts = getOptions (name, src) / / splice directory src/ {template} to produce static file const metalsmith = Metalsmith (path.join (src, 'template')) / / merge meta in metalsmitch with three attributes to form data const data = Object.assign (metalsmith.metadata (), {destDirName: name, inPlace: dest = = process.cwd ()) NoEscape: true}) / / traversing helpers objects in meta.js metadata Register rendering template data / / specify if_or and template_version content opts.helpers & & Object.keys (opts.helpers) .map (key = > {Handlebars.registerHelper (key, opts.helpers [key])}) const helpers = {chalk, logger} / / merge metalsmith metadata data with {isNotTest, isTest} if (opts.metalsmith & typeof opts.metalsmith.before = = 'function') {opts.metalsmith.before (metalsmith, opts) Helpers)} / / askQuestions will ask some questions in the terminal / / name describes what the author wants to build in meta.js 's opts.prompts / / filterFiles is used to filter the file / / renderTemplateFiles is a rendering plug-in metalsmith.use (askQuestions (opts.prompts)) .use (filterFiles (opts.filters)) .use (renderTemplateFiles (opts.skipInterpolation)) if (typeof opts.metalsmith = 'function') {opts.metalsmith (metalsmith, opts) Helpers)} else if (opts.metalsmith & & typeof opts.metalsmith.after = = 'function') {opts.metalsmith.after (metalsmith, opts) The helpers)} / / clean method sets whether to delete the original destination directory before writing. The default is true / / source. The default method is to set the original path / / destination method is to set the output directory / / build method to execute build metalsmith.clean (false) .source ('.) / / start from template root instead of `. / src`which is Metalsmith's default for `source`destination (dest) .build (err) Files) = > {done (err) if (typeof opts.complete = 'function') {/ / execute the opts.complete method const helpers = {chalk, logger, files} opts.complete (data, helpers)} else {logMessage (opts.completeMessage, data)}) return data} copy the code in meta.js after the generation is completed

Meta.js

Next, take a look at the following complete method

Complete: function (data, {chalk}) {const green = chalk.green / / will reorder the existing packagejoson dependency statements sortDependencies (data, green) const cwd = path.join (process.cwd (), data.inPlace?': data.destDirName) / / do you need to automatically install this if (data.autoInstall) {/ / execute the install command installDependencies (cwd, data.autoInstall) in the query before the previous build? Green) .then () = > {return runLintFix (cwd, data, green)}) .then () = > {printMessage (data, green)}) .catch (e = > {console.log (chalk.red ('Error:'), e)})} else {printMessage (data, chalk)} copy the code

Build a custom template

After looking at the principle of the vue-init command, it is actually very simple to customize the custom template. We only need to do two things.

First, we need to have our own template project.

If you need to customize some variables, you need to customize them in the meta.js of the template

Since the download module uses the download-git-repo module, which supports downloading on github,gitlab,bitucket, we only need to put the customized template project on the git remote repository.

Because what I need to define is the development template for Mini Program, and mpvue itself has a template for quickstart, so we customize it on the basis of it. First, we fork it, create a new custom branch, and customize it on this branch.

We need customized places to use dependent libraries that are useful, and we need additional less and wxparse, so we add them in template/package.json

{/ /... Partially omit "dependencies": {"mpvue": "^ 1.0.11" {{# vuex}}, "vuex": "^ 3.0.1" {{/ vuex}, "devDependencies": {/ /. Omit / / this is the added package "less": "^ 3.0.4", "less-loader": "^ 4.1.0", "mpvue-wxparse": "^ 0.6.5"}} copy code

In addition, we also need to customize the eslint rules. Since we only use standard, we can delete airbnb-style questions in meta.js.

"lintConfig": {"when": "lint", "type": "list", "message": "Pick an ESLint preset", "choices": [{"name": "Standard (https://github.com/feross/standard)"," value ":" standard "," short ":" Standard "}, {" name ":" none (configure it yourself) "," value ":" none " "short": "none"}]} copy the code

.eslinttrc.js

'rules': {{# if_eq lintConfig "standard"} "camelcase": 0, / / allow paren-less arrow functions "arrow-parens": 0, "space-before-function-paren": 0, / / allow async-await "generator-star-spacing": 0, {{/ if_eq}} {{# if_eq lintConfig "airbnb"}} / / don't require .vue extension when importing' import/extensions': ['error',' always' {'js':' never', 'vue':' never'}], / / allow optionalDependencies' import/no-extraneous-dependencies': ['error', {' optionalDependencies': ['test/unit/index.js']}], {{/ if_eq}} / / allow debugger during development' no-debugger': process.env.NODE_ENV = = 'production'? 2: 0} copy the code

Finally, in the construction question, we set up a question for the name of Mini Program, and this name will be set to the title of the navigation. The question is added in meta.js.

"prompts": {"name": {"type": "string", "required": true, "message": "Project name"}, / / New question "appName": {"type": "string", "required": true, "message": "App name"}} copy the code

Main.json

{"pages": ["pages/index/main", "pages/counter/main", "pages/logs/main"], "window": {"backgroundTextStyle": "light", "navigationBarBackgroundColor": "# fff", / / set the title "navigationBarTitleText": "{{appName}}", "navigationBarTextStyle": "black"}} copy the code according to the question

Finally, let's try our own template.

Vue init Baifann/mpvue-quickstart#custom min-app-project copy code

Summary

The customization of the above template is very simple, and it is certainly more complex in the actual project, but it should be feasible according to this idea. For example, put some self-encapsulated components into the project, and so on, I will not go into detail here. Principle analysis is based on vue-cli 2.0, but in fact 3.0 is ready to go. If you have the opportunity to understand it in depth, I will share it with you. Thank you.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report