Github.com/roooses/ros…
The framework
egg.js
The core code
const Service = require('egg').Service; const process = require('child_process'); const Metalsmith = require('metalsmith'); const Handlebars = require('handlebars') const download = require('download-git-repo') const path = require('path') const fs = require('fs') const utils = require('./fileUtils'); function resolveData(data) { data.noRepeatCpsName = []; data.outJsList = []; for (let item of data.components) { if (data.noRepeatCpsName.indexOf(item.name) < 0) { data.noRepeatCpsName.push(item.name); } for (let jsItem of item.outJs) { if (data.outJsList.indexOf(jsItem) < 0) { data.outJsList.push(jsItem); } } } return data } function build(data, temp_dest, source, dest, cb, ignore) { if (data.length) { let result = { repoName: data.repoName, version: data.version } data.forEach((pageConfig, index) => { result[`page${index + 1}`] = resolveData(pageConfig) }) data = result } else { data = resolveData(data) } let metalsmith = Metalsmith(temp_dest) .use(renderTemplateFiles(data)) .source(source) .destination(dest) .clean(false) if (ignore) { metalsmith.ignore(filePath => { filePath = filePath.replace(path.join(temp_dest, source), '') filePath = path.join(dest, filePath) return fs.existsSync(filePath) }) } return metalsmith.build((error, files) => { if (error) console.log(error); let f = Object.keys(files) .filter(o => fs.existsSync(path.join(dest, o))) .map(o => path.join(dest, o)) cb(error, f) }) } function renderTemplateFiles(data) { return function (files) { Object.keys(files).forEach((fileName) => { Console. log(fileName) let file = files[fileName] // Render method file.contents = Handlebars.compile(file.contents.toString())(data) }) } } function downloadFunc(downloadRepoUrl, temp_dest) { return new Promise(async (resolve, reject) => { console.log(downloadRepoUrl); download(downloadRepoUrl, temp_dest, {clone: true}, (err) => { if (err) { console.log(err); Reject (' template download failed '); } else {resolve(' Request template download successful '); }})}); } function buildFunc(req, temp_dest) { return new Promise(async (resolve, reject) => { req.templateConfig.port = await utils.getPort(); if (req.templateConfig.port) { build(req.templateConfig, temp_dest, 'template', req.templateConfig.repoName, (err, f) => { if (err) { reject(err); } else {console.log('to repoName complete ') resolve(req.templateconfig. Port); }})} else {reject(' port not available '); }}); } class TplService extends Service { async renderTpl(req, tplDetail) { return new Promise(async (resolve, reject) => { Handlebars.registerHelper('upcasefirst', function (value) { let str = ''; let arr = value.split('-'); for (let item of arr) { str += item[0].toUpperCase() + item.slice(1); } return str; }); Handlebars.registerHelper('tostring', function (value) { return JSON.stringify(value); }); Handlebars.registerHelper('parse', function (value) { let result = ''; Object.keys(value).forEach((key) => { result += `\:${key}\=\'${value[key]}\' ` }); return result; }); if (! (await utils.existOrNot('./static'))) { await utils.mkdirFolder('static'); } // const temp_dest = 'static/ TMP ${req.templateId} tmp${req.templateId}/${req.templateConfig.repoName}`, async function (error, stdout, stderr) { if (error) { reject(error); } else { let hasExist = await utils.existOrNot(`./static/tmp${req.templateId}`); if (! hasExist) { console.log('temp_dest:', temp_dest) let downloadRes = await downloadFunc(req.templateConfig.repoUrl, temp_dest); } let port = await buildFunc(req, temp_dest); resolve(port); } }) }) } } module.exports = TplService;Copy the code
Code parsing
When the render request is submitted in the background, our Node service does the following:
-
Pull the corresponding template
-
Render data
-
compile
To pull a template from a repository, use the download-git-repo plugin. Compilation is all about using the Metalsmith static template generator to take the template as input, the data as padding, and regular rendering using handlebars syntax. Finally output build built directory. In this step, the components we previously needed will be rendered into package.json. Let’s look at the core code:
// This is like a pipe, with the data entry as the source. Function build(data, temp_dest, source, dest, cb) { let metalsmith = Metalsmith(temp_dest) .use(renderTemplateFiles(data)) .source(source) .destination(dest) .clean(false) return metalsmith.build((error, files) => { if (error) console.log(error); let f = Object.keys(files) .filter(o => fs.existsSync(path.join(dest, o))) .map(o => path.join(dest, o)) cb(error, f) }) } function renderTemplateFiles(data) { return function (files) { Object.keys(files).forEach((fileName) => { let File = files[fileName] // render file.contents = handlebars.compile (file.contents. ToString ())(data)})}}Copy the code
What we end up with is a Vue project that doesn’t run directly in the browser at this point, which is where the current distribution system supports it. How do you say? If your company’s distribution system requires online compilation, you can upload the source files directly to your Git repository, trigger the repository’s WebHook, and have the distribution system release the project for you. If your distribution system requires you to compile and submit a compilation file for distribution, you can use the Node command to build locally and produce HTML, CSS, and JS. Submit it directly to the publishing system.
release
The final result is a Vue project. The project file is in the same directory as rose-server in port. At this point, it cannot run directly in the browser
If your company’s distribution system requires online compilation, you can upload the source files directly to your Git repository, trigger the repository’s WebHook, and have the distribution system release the project for you
If your distribution system requires you to compile and submit a compilation file for distribution, you can use the Node command to build locally and produce HTML, CSS, and JS