美文网首页
前端工程化

前端工程化

作者: lowpoint | 来源:发表于2021-01-14 21:47 被阅读0次

    为何工程化

    在我们的实际开发中,我们想用最新的es语法,想用less,sass等样式预处理。我们想要使用模块化的方式提高项目的可维护性,但是运行环境却不支持。多人协作,代码风格不统一。发布上线需要手动压缩与上传,这些问题的出现需要我们去有一种方式去解决这些问题。工程化就是解决这些问题的一个体现。

    工程化的体现

    一切以提高效率,降低成本,质量保证为目的的手段都属于工程化。
    一些成熟的工程化集成 如vue-cli , angular-cli , create-react-app
    前端工程化的实现 nodejs有巨大贡献。

    脚手架工具yeoman的使用

    1.全局安装yo

    cnpm i yo -g //或者 yarn global add yo
    

    2.安装对应的generator

    npm i generator-node -g //或者 yarn global add generator-node
    

    3.通过yo运行generator

    yo node
    
    yeoman的sub generator使用

    1.明确需求。
    2.找到合适的Generator。
    3.全局范围安装找到的Generator。
    4.通过yo安装找到的Generator。
    5.通过命令交互填写选项。
    6.生成所需要的项目结构。

    自定义Generator

    基于yeoman搭建自己的脚手架
    1.创建Generator模块(generator本质上就是一个NPM模块)


    图片.png

    yeoman的generator模块名称必须是 generator-<name>

    mkdir generator-sample //创建文件
    cd generator-sample 
    yarn init //初始化
    yarn add yeoman-generator //安装基类 提供了一些方法
    

    按照格式创建


    图片.png
    //作为generator核心入口
    //需要导出一个继承自 yeoman generator的类型
    //yeoman generator  在工作时会自动调用我们在此类型中定义的一些声明周期方法
    //在这些方法中可以通过调用父类提供的一些工具方法实现一些功能  比如文件写入
    
    const Generator = require('yeoman-generator')
    
    module.exports = class extends Generator {
      writing() {
        //yoman 自动在生成文件阶段调用此方法
        //我们在这里尝试往项目目录中写入文件
        // this.fs.write(
        //   this.destinationPath('test.txt'),
        //   Math.random().toString()
        // )
    
        //通过模板方式写入文件到目标目录
        //三个参数 1.模板文件路径 2.输出文件路径 3.模板数据上下文
        const tmpl = this.templatePath('foo.txt')//模板文件路径
        const output = this.destinationPath('foo.txt')//模板文件路径
        const context = { title: 'hello tem', success: true }//模板数据上下文
        this.fs.copyTpl(tmpl, output, context)
      }
    }
    

    通过yarn link链接到全局范围 使其成为一个全局模块包

    yarn link
    

    在其它地方就可以运行这个生成器

    yo sample //刚才起的生成器名称
    

    创建一个自己的vue Generator

    mkdir generator-my-vue
    cd generator-my-vue
    yarn init
    yarn add yeoman-generator
    code . //vscode 打开文件
    

    1.还是先创建模板文件


    图片.png

    2.写模板代码

    const Generator = require('yeoman-generator')
    
    module.exports = class extends Generator{
      prompting(){
        return this.prompt([
          {
            type:'input',
            name:'name',
            message:'your project name',
            default:this.appname
          }
        ])
        .then(answers => {
          this.answers = answers
        })
      }
      writing(){
        
      }
    }
    

    3.将项目结构放入template文件夹中


    图片.png

    4.将项目结构可能发生变化的地方用模板语法替换 如:


    图片.png
    1. yarn link 到全局
      6.使用 yo my-vue 安装到对应目录

    发布generator

    //先创建一个本地的git仓库
    //先创建一个gitignore
    echo node_modules > .gitignore
    //初始化一个本地空仓库
    git init
    //查看本地仓库状态
    git status
    
    git add .
    //创建一次提交
    git commit -m "initial commit"
    
    //提交到远端仓库
    //创建一个远端新仓库 gitee或者github
    git remote add origin https://gitee.com/wkpkko/generator-myvue.git
    //这样为本地仓库添加了一个远端仓库的别名 push的时候可以使用这个别名
    git push -u origin master //推送到远端仓库
    //通过npm publish 发布这个模块  yarn publish 
    yarn publish
    //在使用淘宝镜像发布时会出现问题
    //发布的时候设置镜像
    yarn publish --registry=https://registry.yarnpkg.com
    //自动推送到yarn的官方镜像  yarn的镜像与npm镜像时同步的  此时模块发布成功了
    
    //在npm官网  npmjs.com/package/generator-myvue 
    //此时模块已经被推送上来了
    

    Plop一个小而美的脚手架工具

    主要用于创建项目中特定类型文件的一个小工具,类似与yeoman中的subgeneraor,一般不会单独使用。一般会把plop集成在项目中,用来自动化创建同类型的项目文件

    yarn add plop --dev
    

    在项目根目录下创建plopfile.js

    // Plop 入口文件,需要导出一个函数
    // 此函数接收一个 plop 对象,用于创建生成器任务
    
    module.exports = plop => {
      plop.setGenerator('component', {
        description: 'create a component',
        prompts: [
          {
            type: 'input',
            name: 'name',
            message: 'component name',
            default: 'MyComponent'
          }
        ],
        actions: [
          {
            type: 'add', // 代表添加文件
            path: 'src/components/{{name}}/{{name}}.js',
            templateFile: 'plop-templates/component.hbs'
          },
          {
            type: 'add', // 代表添加文件
            path: 'src/components/{{name}}/{{name}}.css',
            templateFile: 'plop-templates/component.css.hbs'
          },
          {
            type: 'add', // 代表添加文件
            path: 'src/components/{{name}}/{{name}}.test.js',
            templateFile: 'plop-templates/component.test.hbs'
          }
        ]
      })
    }
    

    创建模板文件
    plop-templates/component.hbs

    import React from 'react';
    
    export default () => (
      <div className="{{name}}">
        <h1>{{name}} Component</h1>
      </div>
    )
    

    component.css.hbs

    .{{name}} {
      
    }
    

    component.test.hbs

    import React from 'react';
    import ReactDOM from 'react-dom';
    import {{name}} from './{{name}}';
    
    it('renders without crashing', () => {
      const div = document.createElement('div');
      ReactDOM.render(<{{name}} />, div);
      ReactDOM.unmountComponentAtNode(div);
    });
    
    

    yarn plop component (刚才定义的生成器的名称)

    脚手架工作原理

    大部分脚手架都是设置一些问题,通过这些问题为你创建一些模板的项目结构。
    脚手架工具就是一个nodecli应用。
    通过nodejs开发一个小型的脚手架工具

    mkdir sample-cli
    cd sample-cli
    yarn init//初始化一个package.json文件
    
    //package.json中添加bin字段作为cli的入口文件
    {
      "name": "sample-cli",
      "version": "1.0.0",
      "description": "sample cli",
      "bin":"cli.js",
      "main": "index.js",
      "license": "MIT"
    }
    

    创建cli.js
    cli文件必须要有一个特定的文件头

    #!/usr/bin/env node
    
    // Node CLI 应用入口文件必须要有这样的文件头
    // 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
    // 具体就是通过 chmod 755 cli.js 实现修改
    console.log('sample cli')
    

    通过yarn link 链接到全局
    此时就可以使用sample-cli命令执行


    图片.png
    // 脚手架的工作过程:
    // 1. 通过命令行交互询问用户问题
    // 2. 根据用户回答的结果生成文件
    

    node通过用户询问 我们使用inquirer模块

    yarn add inquirer
    此时我们可以在cli.js载入它

    const inquirer = require('inquirer')
    inquirer.prompt([
      {
        type: 'input',
        name: 'name',
        message: 'Project name?'
      }
    ]).then(answer => {
      console.log(answer)
    })
    
    图片.png

    创建模板文件


    图片.png
    #!/usr/bin/env node
    
    // Node CLI 应用入口文件必须要有这样的文件头
    // 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
    // 具体就是通过 chmod 755 cli.js 实现修改
    
    //脚手架的工作过程
    //1.通过命令行交互询问用户问题
    //2.根据用户回答的结果生成文件
    const path = require('path')
    const fs = require('fs')
    const inquirer = require('inquirer')
    
    inquirer.prompt([
      {
        type: 'input',
        name: 'name',
        message: 'Project name?'
      }
    ]).then(answer => {
      //根据用户回答结果生成文件
    
      //模板目录
      const templDir = path.join(__dirname,'templates')
      //输出目录 命令行执行路径
      const destDir = process.cwd()
      //将模板下的文件全部转换到目录 fs的readdir方法会自动扫描目录下所有文件
      fs.readdir(templDir,(err,files) => { //files拿到所有文件列表
        if(err) throw err
        files.forEach(file => {
          // console.log(file) //每个file就是相对于templates下的相对路径
          //可以通过模板引擎去渲染这个路径所对应的文件
          
        })
      })
    
    })
    

    先安装对应的模板引擎 (安装一个ejs模板引擎)

    yarn add ejs
    之后引入模板引擎

    #!/usr/bin/env node
    
    // Node CLI 应用入口文件必须要有这样的文件头
    // 如果是 Linux 或者 macOS 系统下还需要修改此文件的读写权限为 755
    // 具体就是通过 chmod 755 cli.js 实现修改
    
    //脚手架的工作过程
    //1.通过命令行交互询问用户问题
    //2.根据用户回答的结果生成文件
    const path = require('path')
    const fs = require('fs')
    const inquirer = require('inquirer')
    const ejs = require('ejs')
    
    inquirer.prompt([
      {
        type: 'input',
        name: 'name',
        message: 'Project name?'
      }
    ]).then(answer => {
      //根据用户回答结果生成文件
    
      //模板目录
      const templDir = path.join(__dirname, 'templates')
      //输出目录 命令行执行路径
      const destDir = process.cwd()
      //将模板下的文件全部转换到目录 fs的readdir方法会自动扫描目录下所有文件
      fs.readdir(templDir, (err, files) => { //files拿到所有文件列表
        if (err) throw err
        files.forEach(file => {
          // console.log(file) //每个file就是相对于templates下的相对路径
          //可以通过模板引擎去渲染这个路径所对应的文件
          //renderFile三个参数 1.文件的绝对路径 2.工作时的数据上下文answer 3.回调函数
          ejs.renderFile(path.join(templDir, file), answer, (err, result) => {
            if (err) throw err
            //通过文件写入写入到目标目录
            fs.writeFileSync(path.join(destDir, file), result)
          })
        })
      })
    
    })
    

    资料来源:拉勾教育-前端训练营

    相关文章

      网友评论

          本文标题:前端工程化

          本文链接:https://www.haomeiwen.com/subject/ksjbaktx.html