源码共读-UMI-3

接上一个博客源码共读-UMI-2,接下来,我们来继续执行 umi generate
第一个博客中我们知道,执行umi generate 会执行lib/scripts/ generate.js

lib/scripts/generate.js

import yParser from 'yargs-parser';
import generate from '../generate';

const argv = yParser(process.argv.slice(2));
const [type, file] = argv._;

generate({
  type,
  file,
  useClass: argv.c || argv.class || false,
  isDirectory: argv.d || argv.directory || false,
});

取出参数调用generate

../generate.js

import assert from 'assert';
import page from './generators/page';

const generators = {
  page,
};

这里应该是为了后续扩展使用的,这里暂时只有一个page

export default function(opts = {}) {
  const { type, file } = opts;
  assert(type, 'opts.type should be supplied');
  assert(typeof type === 'string', 'opts.file should be string');
  assert(file, 'opts.file should be supplied');
  assert(typeof file === 'string', 'opts.file should be string');
  assert(generators[type], `generator of type (${type}) not found`);

  delete opts.type;
  generators[type](opts);
}

./generators/page

import assert from 'assert';

该模块用于编写应用程序的单元测试

import ejs from 'ejs';

嵌入式JavaScript模板

import uppercamelcase from 'uppercamelcase';

首字母大写转换 如 foo-bar => FooBar

import { join, basename } from 'path';
import { existsSync, statSync, readFileSync, writeFileSync } from 'fs';
属性 说明
existsSync 测试某个路径下的文件是否存在
statSync 获取文件信息
readFileSync 读取文件
writeFileSync 写文件
//目录存在
function directoryExists(path) {
  return existsSync(path) && statSync(path).isDirectory();
}
//文件存在
function fileExists(path) {
  return existsSync(path) && statSync(path).isFile();
}
//去除空行
function stripEmptyLine(content) {
  const ret = content
    .trim()
    // 两行 -> 一行
    .replace(/\n\n/g, '\n');

  // 结尾空行
  return `${ret}\n`;
}
//看一下代码时,可先忽略assert
export default function(opts = {}) {
  const { file } = opts;
  //断言
  assert(
    !('isDirectory' in opts) || typeof opts.isDirectory === 'boolean',
    'opts.isDirectory should be boolean',
  );
  assert(
    !('useClass' in opts) || typeof opts.useClass === 'boolean',
    'opts.useClass should be boolean',
  );
  //目录
  const isDirectory = opts.isDirectory || false;
  //当前执行路径
  const cwd = opts.cwd || process.cwd();

  console.log(`[DEBUG] generate page ${file} with isDirectory ${isDirectory}`);

  let cssTargetPath;
  let jsTargetPath;
//是目录的时候,在file目录下新建page文件
//不是目录的时候,新建file文件
  if (isDirectory) {
    assert(
      !directoryExists(join(cwd, 'src', 'page', file)),
      `directory src/page/${file} exists`,
    );
    jsTargetPath = join(cwd, 'src', 'page', file, 'page.js');
    cssTargetPath = join(cwd, 'src', 'page', file, 'page.css');
  } else {
    jsTargetPath = join(cwd, 'src', 'page', `${file}.js`);
    cssTargetPath = join(cwd, 'src', 'page', `${file}.css`);
  }

  assert(!fileExists(jsTargetPath), `file src/page/${file} exists`);
  assert(!fileExists(cssTargetPath), `file src/page/${file} exists`);

  //从模板中读取文件
  const jsTpl = readFileSync(
    join(__dirname, '../../template/page.js'),
    'utf-8',
  );
  const cssTpl = readFileSync(
    join(__dirname, '../../template/page.css'),
    'utf-8',
  );


  const fileName = basename(file);
  const componentName = uppercamelcase(fileName);
  //使用ejs render文件
  //ejs.render(str, data, options);
  //options https://www.npmjs.com/package/ejs#options
  const jsContent = ejs.render(
    jsTpl,
    {
      useClass: opts.useClass,
      fileName,
      componentName,
    },
    {
      _with: false,
      localsName: 'umi',
    },
  );

  const cssContent = ejs.render(
    cssTpl,
    {},
    {
      _with: false,
      localsName: 'umi',
    },
  );

  //写入文件
  writeFileSync(jsTargetPath, stripEmptyLine(jsContent), 'utf-8');
  writeFileSync(cssTargetPath, stripEmptyLine(cssContent), 'utf-8');
}

本节课就到此结束了,喜欢我的博客的朋友可以关注我。后续会有实战演练哦。
Github地址
https://github.com/xiaohuoni/source-code-co-reading-umi

感谢您的阅读。
我是莽夫,希望你开心。
如果你觉得本文对你有帮助,请扫描文末二维码,支持博主原创。
希望大家关注我的个人公众号ionic_
这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章