Part2.模塊一:開發(fā)腳手架及封裝自動化構建工作流

簡答題

1.談談你多工程化的初步認識,結合你之前遇到過的問題說出三個以上工程化能夠解決問題或者帶來的價值午笛。

解:
??????工程化指的是在遵循一定標準和規(guī)范的基礎上府怯,通過使用工具來提高效率煎饼,降低成本的一種手段;工程化不等于某種工具谤专,一切以提高效率躁锡、降低成本和質(zhì)量保證為目的的手段都稱之為工程化。
解決的問題:
??????1.無法使用模塊化/組件化組織代碼
??????2.代碼風格統(tǒng)一置侍,使得項目多人協(xié)作開發(fā)稚铣,質(zhì)量得以保證
??????3.部分功能需要等待后端服務接口完成以后才可以進行開發(fā)
??????4.重復的機械工作,比如部署上線前需要手動壓縮代碼及資源文件墅垮,部署過程需要手動上傳代碼到服務器惕医。
帶來的價值:
??????1.壓縮圖片大小,使得請求圖片時間降低
??????2.代碼合并壓縮算色,減少項目整體體積

2.你認為腳手架除了為我們創(chuàng)建項目結構抬伺,還有什么更深的意義。

解:
??????腳手架的本質(zhì)作用除了為我們創(chuàng)建項目結構灾梦,還為我們提供了項目規(guī)范和約定峡钓。腳手架創(chuàng)建的項目包含相同的組織結構、相同的開發(fā)范式若河、相同的模塊依賴能岩、相同的工程配置以及相同的基礎代碼。腳手架作為一種創(chuàng)建項目初始文件的工具被廣泛地應用于新項目或迭代初始階段萧福。使用工具代替人工操作能夠避免人為失誤引起的低級錯誤拉鹃,同時結合整體前端工程化方案,快速生成功能模塊配置、自動安裝依賴等膏燕,優(yōu)化了時間成本钥屈。在公司中使用同一套腳手架工具創(chuàng)建的項目,使得項目成員更換時坝辫,能夠馬上上手篷就,提高開發(fā)效率。

編程題

1.概述腳手架是實現(xiàn)的過程近忙,并使用NodeJS完成一個自定義的小型腳手架工具竭业。

解:
??????實現(xiàn):
??????1.創(chuàng)建一個新的倉庫目錄:small-node-js
??????2.通過yarn init --yes初始化項目并生成package.json文件
??????3.創(chuàng)建cli.js文件,并將其路徑添加到package.json中bin對應的值

{
  "name": "small-node-js",
  "version": "1.0.0",
  "main": "index.js",
  "bin": "lib/cli.js",
  "license": "MIT",
  "devDependencies": {},
  "dependencies": {
    "ejs": "^3.1.3",
    "inquirer": "^7.3.3"
  }
}

??????4.編寫cli.js中的內(nèi)容

#!/usr/bin/env node

// Node CLI 應用入口文件必須要有這樣的文件頭
// 如果Linux 或者 Mac 系統(tǒng)下及舍,還需要修改此文件權限為755: chmod 755 cli.js

// 腳手架工作過程:
// 1. 通過命令行交互詢問用戶問題
// 2. 根據(jù)用戶回答的結果生成文件

const path = require('path')
const fs = require('fs')  // 讀取文件
const inquirer = require('inquirer') // 發(fā)起命令行交互詢問
const ejs = require('ejs') // 模板引擎
inquirer.prompt([
  {
    type: 'input',
    name: 'title',
    message: 'Project name?'
  },
  {
    type: 'input',
    name: 'name',
    message: 'your name?'
  },
  {
    type: 'input',
    name: 'age',
    message: 'your age?'
  },
]).then(answer => {

  // 模板目錄
  const tempDir = path.join(__dirname, 'templates')
  // 目標目錄  --當前文件夾路徑
  const destDir = process.cwd()

  // 將模板下的文件全部轉換到目標目錄
  fs.readdir(tempDir, (err, files) => {
    if (err) throw err
    files.forEach(file => {
      // 通過模板引擎渲染文件
      ejs.renderFile(path.join(tempDir, file), answer, (err, result) => {
        if(err) throw err
        // 將結果寫入到目標目錄
        fs.writeFileSync(path.join(destDir, file), result)
      })
    })
  })
})

??????5.創(chuàng)建模板文件index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= title %></title>
</head>
<body>
  <p><%= name %></p>
  <p><%= age %></p>
</body>
</html>

??????6.執(zhí)行yarn link命令將該cli程序link到全局
??????7.在命令行中執(zhí)行small-node-js未辆,,并根據(jù)提示輸入相應的值,則會在項目根目錄下創(chuàng)建由該模板生成的index.html


NodeJS腳手架.png
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>nodejs</title>
</head>
<body>
  <p>Tom</p>
  <p>18</p>
</body>
</html>
2.嘗試使用Gulp完成項目的自動化構建击纬。

視頻地址Gulp腳手架-項目自動化構建
Gulp講解:

  • gulpfile.js
// 實現(xiàn)這個項目的構建任務
//導入 gulp 下需要使用到的庫
const { src, dest, parallel, series, watch} = require('gulp')
const del = require('del')

// 自動加載插件
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
const {sass, babel, swig, imagemin, uglify, cleanCss, htmlmin} = plugins

// 提供開發(fā)服務器,在代碼修改后能夠熱更新
const browserSync = require('browser-sync')
const bs = browserSync.create()

const data = {
    menus: [
      {
        name: 'Home',
        icon: 'aperture',
        link: 'index.html'
      },
      {
        name: 'Features',
        link: 'features.html'
      },
      {
        name: 'About',
        link: 'about.html'
      },
      {
        name: 'Contact',
        link: '#',
        children: [
          {
            name: 'Twitter',
            link: 'https://twitter.com/w_zce'
          },
          {
            name: 'About',
            link: 'https://weibo.com/zceme'
          },
          {
            name: 'divider'
          },
          {
            name: 'About',
            link: 'https://github.com/zce'
          }
        ]
      }
    ],
    pkg: require('./package.json'),
    date: new Date()
}

// 文件清除
const clean = () => {
    return del(['dist', 'temp'])
}
// 樣式編譯
const style = () => {
    return src('src/assets/styles/*.scss', { base: 'src'})
        .pipe(sass({outputStyle: 'expanded'}))
        .pipe(dest('temp'))
        .pipe(bs.reload({stream: true}))
}

// 腳本編譯
const script = () => {
    return src('src/assets/scripts/*.js', { base: 'src'})
        .pipe(babel({presets: ['@babel/preset-env']}))
        .pipe(dest('temp'))
        .pipe(bs.reload({stream: true}))
}

// 模板編譯
const page = () => {
    return src('src/*.html', { base: 'src'})
        .pipe(swig({data, defaults: {cache: false}})) // 防止模板緩存導致頁面不能及時更新
        .pipe(dest('temp'))
        .pipe(bs.reload({stream: true}))
}


// 圖片壓縮
const image = () => {
    return src('src/assets/images/**', { base: 'src'})
        .pipe(imagemin())
        .pipe(dest('dist'))
}

// 字體壓縮
const font = () => {
    return src('src/assets/fonts/**', { base: 'src'})
        .pipe(imagemin())
        .pipe(dest('dist'))
}

// 額外的編譯:public
const extra = () => {
    return src('public/**', {base: 'public'})
        .pipe(dest('dist'))
}


// 開發(fā)服務器
const server = () => {
    // 監(jiān)視文件钾麸,決定是否要執(zhí)行任務
    watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
    //watch('src/assets/images/**', image)
    //watch('src/assets/fonts/**', font)
    //watch('public/**', extra)

    watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
    ], bs.reload)

    // 初始化服務器的相關配置
    bs.init({
        notify:false, 
        port:2080,
        // files:'dist/**',
        server: {
            baseDir:['temp', 'src', 'public'],//圖片只是壓縮了更振,請求dist和src上并無區(qū)別,只是進行壓縮了下饭尝,這里讓他請求原文件肯腕,減少了一次構建,提高開發(fā)效率
            routes:{
                '/node_modules' : 'node_modules'
            }
        }
    })
}

// 文件引用處理---合并
const useref = () => {
    return src('temp/*.html',{base: 'temp'})
        .pipe(plugins.useref({searchPath: ['temp','.']}))
        .pipe(plugins.if(/\.js$/,uglify()))
        .pipe(plugins.if(/\.css$/,cleanCss()))
        .pipe(plugins.if(/\.html$/,htmlmin({
            collapseWhitespace: true, // 折疊空白字符和換行符
            minifyCSS: true, // 樣式壓縮
            minefyJS: true // 腳本壓縮
        })))
        .pipe(dest('dist'))
}
// 編譯任務
const compile = parallel(style, script, page)

// 完成所有文件的編譯   上線之前執(zhí)行的任務
const build = series(
    clean,
    parallel(     
        series(compile, useref), 
        image, 
        font, 
        extra
    )
)

// 開發(fā)任務
const develop = series(compile, server)
module.exports = {
    build,
    develop,
    compile,
}

/**
 * 運行命令
 * yarn gulp build
 * yarn gulp develop
 * yarn gulp compile
 */
  • pacjage.json
{
  "name": "pages-boilerplate",
  "version": "0.1.0",
  "private": true,
  "description": "Always a pleasure scaffolding your awesome static sites.",
  "keywords": [
    "pages-boilerplate",
    "boilerplate",
    "pages",
    "zce"
  ],
  "homepage": "https://github.com/zce/pages-boilerplate#readme",
  "bugs": {
    "url": "https://github.com/zce/pages-boilerplate/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/zce/pages-boilerplate.git"
  },
  "license": "MIT",
  "author": {
    "name": "zce",
    "email": "w@zce.me",
    "url": "https://zce.me"
  },
  "scripts": {
    "clean": "gulp clean",
    "lint": "gulp lint",
    "serve": "gulp serve",
    "build": "gulp build",
    "start": "gulp start",
    "deploy": "gulp deploy --production"
  },
  "browserslist": [
    "last 1 version",
    "> 1%",
    "maintained node versions",
    "not dead"
  ],
  "dependencies": {
    "bootstrap": "4.4.1",
    "jquery": "3.4.1",
    "popper.js": "1.16.1"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/preset-env": "^7.11.0",
    "browser-sync": "^2.26.12",
    "del": "^5.1.0",
    "gulp": "^4.0.2",
    "gulp-babel": "^8.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-htmlmin": "^5.0.1",
    "gulp-if": "^3.0.0",
    "gulp-imagemin": "^7.1.0",
    "gulp-load-plugins": "^2.0.3",
    "gulp-sass": "^4.1.0",
    "gulp-swig": "^0.9.1",
    "gulp-uglify": "^3.0.2",
    "gulp-useref": "^4.0.1"
  },
  "engines": {
    "node": ">=6"
  }
}

3.使用Grunt完成項目的自動化構建钥平。

未完待續(xù)实撒。。涉瘾。知态。。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末立叛,一起剝皮案震驚了整個濱河市负敏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秘蛇,老刑警劉巖其做,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赁还,居然都是意外死亡妖泄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門艘策,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹈胡,“玉大人,你說我怎么就攤上這事∩蟛校” “怎么了梭域?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搅轿。 經(jīng)常有香客問我病涨,道長,這世上最難降的妖魔是什么璧坟? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任既穆,我火速辦了婚禮,結果婚禮上雀鹃,老公的妹妹穿的比我還像新娘幻工。我一直安慰自己,他們只是感情好黎茎,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布囊颅。 她就那樣靜靜地躺著,像睡著了一般傅瞻。 火紅的嫁衣襯著肌膚如雪踢代。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天嗅骄,我揣著相機與錄音胳挎,去河邊找鬼。 笑死溺森,一個胖子當著我的面吹牛慕爬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屏积,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼医窿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炊林?” 一聲冷哼從身側響起留搔,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铛铁,沒想到半個月后隔显,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡饵逐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年括眠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倍权。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掷豺,死狀恐怖捞烟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情当船,我是刑警寧澤题画,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站德频,受9級特大地震影響苍息,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壹置,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一竞思、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钞护,春花似錦盖喷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至余佃,卻和暖如春暮刃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咙冗。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工沾歪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留漂彤,地道東北人雾消。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像挫望,于是被迫代替她去往敵國和親立润。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355