part2_模組一作業

christian-dong發表於2020-10-25

簡答題

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

解答:

  • 傳統語言或語法專案中不能直接支援
  • 無法使用模組化 / 元件化
  • 重複的機械工作
  • 程式碼風格統一/質量保證
  • 依賴後端服務介面支援
  • 整體依賴後端專案

2、你認為腳手架除了為我們建立專案結構,還有什麼更深的意義?

解答:

  • 提供專案規範和約定
  • 將重複工作利用腳手架完成
  • 利用腳手架快速搭建特定專案骨架,後續基於這個骨架進行開發

程式設計題

1、概述腳手架實現的過程,並使用 NodeJS 完成一個自定義的小型腳手架工具

  • 在全域性範圍安裝 yo

     $ npm install yo -- global  # or yarn global add yo
    
  • 建立一個generator-< name > 的資料夾 (< name >為腳手架名稱)

  • 利用yarn init 建立一個package.json

  • 安裝一個yeoman-generator(提供了工具函式)

    yarn add yeoman-generator
    
  • 按照 generator 目錄結構穿件目錄

    generators --> app ---> index.js
    
    	//index.js
    const Generator = require('yeoman-generator')
    module.exports = class extends Generator {
    	// 命令列互動方式獲取資料
    	prompting(){
    		return this.prompt([
    			{
    				type: 'input',
    				name: 'name',
    				mesage: 'Your project name',
    				default: this.appname
    			}
    		]).then(answers => {
    			this.answers = answers
    		})
    	}
    	
    	writing(){
    		// 把每一個檔案通過模板轉換到目標路徑
    		const templates = [ //目標相對路徑陣列
    		  '.browserslistrc',
    		  '.editorconfig',
    		  '.env.development',
    		  '.env.production',
    		  '.eslintrc.js',
    		  '.gitignore',
    		  'babel.config.js',
    		  'package.json',
    		  'postcss.config.js',
    		  'README.md',
    		  'public/favicon.ico',
    		  'public/index.html',
    		  'src/App.vue',
    		  'src/main.js',
    		  'src/router.js',
    		  'src/assets/logo.png',
    		  'src/components/HelloWorld.vue',
    		  'src/store/actions.js',
    		  'src/store/getters.js',
    		  'src/store/index.js',
    		  'src/store/mutations.js',
    		  'src/store/state.js',
    		  'src/utils/request.js',
    		  'src/views/About.vue',
    		  'src/views/Home.vue'
    		]
    		
    		templates.forEach(item => {
    			// item => 每個檔案路徑
    			this.fs.copyTpl(
    			  this.templatePath(item),
    			  this.destinationPath(item),
    			  this.answers
    			)
    		})
    	}
    }
    
  • 通過 yarn link 到全域性

  • 在新的工作目錄 執行 yo < name >

  • 釋出 Generator
    將程式碼託管到GitHub倉庫

    echo node_modules > .gitignore  //忽略 node_modules 檔案提交
    git init  //初始化 git 倉庫
    git status  //檢視倉庫狀態
    git add .
    git commit -m "meat: initial commit"
    git remote add origin 遠端倉庫地址   // 為遠端倉庫新增一個別名
    git push -u origin master 
    

    通過 yarn publish 釋出

2、嘗試使用 Gulp 完成專案的自動化構建

  • 對專案進行分析,需要對HTML、SCSS、JS進行構建並壓縮,對圖片字型檔案進行壓縮
  • 1、將 scss 檔案轉換成css檔案 gulp-sass
  • 2、將 js 檔案中 es6 新特性轉換 gulp-babel @babel/core @babel/preset-env
  • 3、處理頁面中的模板語法 gulp-swig 將動態資料新增到模板引擎中
  • 4、壓縮 img 圖片 gulp-imagemin
  • 5、壓縮 字型檔案 gulp-imagemin
  • 6、建立編譯任務 用 parallel 將 scss js HTML img font 並行處理
  • 7、拷貝 public 檔案下的所有檔案
  • 8、建立專案編譯任務 build 將 6,7 中任務合併處理
  • 9、自動清除 dist 目錄下的檔案 del
  • 10、將 9 中的清除任務新增到 8 中,先清除後編譯
  • 11、通過 gulp-load-plugins 自動載入外掛,運用的外掛越來越多手動載入不方便
  • 12、啟動開發伺服器 – 自動編譯和重新整理檔案改變時進行編譯操作
  • 13、構建 start 任務啟動服務前先編譯生成 dis 目錄
  • 14、處理頁面中 引用模組 URL 路徑問題 gulp-useref
  • 15、對 useref 處理的檔案進行壓縮 利用 plugins.if 判斷型別做不同的操作 gulp-htmlmin gulp-uglify gulp-clean-css gulp-if
  • 16、解決 useref 讀寫衝突寫入新的目錄內
  • 17、重新規劃目錄結構
    const {src, dest, parallel, series, watch} = require('gulp')
    
    const del = require('del')
    const browserSync = require('browser-sync')
    const bs = browserSync.create()
    
    const loadPlugins = require('gulp-load-plugins')
    const plugins = loadPlugins()
    
    const clean = () => {
    	return del(['dist', 'temp'])
    }
    
    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 style = () => {
    	return src('src/assets/styles/*.scss',{base: 'src'})
    		.pipe(plugins.sass({outputStyle: 'expanded'}))
    		.pipe(dest('temp'))
    		.pipe(bs.reload({ stream: true })) //以流的形式上推
    }
    
    const script = () => {
    	return src('src/assets/scripts/*.js',{base: 'src'})
    	.pipe(plugins.babel({presets: ['@babel/preset-env']}))
    	.pipe(dest('temp'))
    	.pipe(bs.reload({ stream: true })) //以流的形式上推
    }
    
    const page = () => {
    	return src('src/*.html',{base: 'src'})
    	.pipe(plugins.swig({data, defaults: { cache: false }})) // 防止模板快取導致頁面不能及時更新
    	.pipe(dest('temp'))
    	.pipe(bs.reload({ stream: true })) //以流的形式上推
    }
    
    const image = () => {
    	return src('src/assets/images/**',{base: 'src'})
    	.pipe(plugins.imagemin())
    	.pipe(dest('dist'))
    }
    
    const font = () => {
    	return src('src/assets/fonts/**',{base: 'src'})
    	.pipe(plugins.imagemin())
    	.pipe(dest('dist'))
    }
    
    const compile = parallel(style, script, page)
    
    const extra = () => {
    	return src('public/**',{base: 'public'})
    	.pipe(dest('dist'))
    }
    
    const serve = () => {
    	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,
    		// open: false,
    		// files: 'dist/**', // 監聽 dist 檔案變化重新整理
    		server: {
    			baseDir: ['temp', 'src', 'public'],
    			routes: {
    				'/node_modules': 'node_modules'
    			}
    		}
    	})
    }
    
    const start = series(compile, serve)
    
    const useref = () => {
    	return src('temp/*.html',{base: 'temp'})
    	.pipe(plugins.useref({searchPath: ['temp', '.']}))
    	.pipe(plugins.if(/\.js$/, plugins.uglify()))
    	.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
    	.pipe(plugins.if(/\.html$/, plugins.htmlmin({
    		collapseWhitespace: true,
    		minifyCSS: true,
    		minifyJS: true
    	})))
    	.pipe(dest('dist'))
    }
    
    const build = series(clean, parallel(series(compile,useref), image, font, extra))
    
    module.exports = {
    	build,
    	clean,
    	serve,
    	start
    }
    

3、使用 Grunt 完成專案的自動化構建
實現這個專案的構建任務
需要對 src 下的檔案進行編譯和 public 專案中的檔案最終都編譯到dist 目錄並且啟動一個sever自動更新修改的結果

  • 1、安裝 load-grunt-tasks 自動載入所有的 grunt 外掛中的任務

  • 2、處理專案中的 css 檔案 grunt-sass sass

  • 3、處理專案中的 js 檔案 @babel/core @babel/preset-env grunt-babel

  • 4、處理頁面中的模板語法 grunt-swigtemplates 將動態資料新增到模板引擎中

  • 5、img 圖片,fonts 字型處理 grunt-contrib-imagemin

  • 6、拷貝 public 檔案下的所有檔案到 dist 目錄 grunt-contrib-copy

  • 7、建立編譯任務 將處理完的檔案集體編譯到 dist 目錄

  • 8、 自動清除 dist 目錄下的檔案 grunt-contrib-clean

  • 9、啟動開發伺服器 – grunt-browser-sync

  • 10、監聽檔案的變化後自動編譯 grunt-contrib-watch

  • 11、處理頁面中引用模組 URL 路徑問題 grunt-useref grunt-css grunt-contrib-uglify grunt-contrib-concat

  • 12、壓縮html grunt-contrib-htmlmin

  • 13、構建build任務

    const loadGruntTasks = require('load-grunt-tasks')
    const sass = require('sass')
    
    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()
    }
    
    module.exports = grunt => {
    	grunt.initConfig({
    		sass: {
    			options: {
    				// sourceMap: true,
    				implementation: sass
    			},
    			dist: {
    			  files: [{
    				expand: true,
    				cwd: 'src/assets/styles',
    				src: ['*.scss'],
    				dest: 'dist/assets/styles',
    				ext: '.css'
    			  }]
    			}
    		},
    		babel:{
    			options: {
    			  // sourceMap: true,
    			  presets: ['@babel/preset-env']
    			},
    			dist: {
    			  files:[{
    				expand: true,
    				cwd: 'src/assets/scripts',
    				src: ['*.js'],
    				dest: 'dist/assets/scripts'
    			  }] 
    			}
    		},
    		swigtemplates: {
    		  options: {
    		    defaultContext: data,
    		    templatesDir: 'src'
    		  },
    		  production: {
    		    dest: 'dist',
    		    src: ['src/*.html']
    		  }
    		},
    		imagemin: {
    			dist: {
    				options: {
    					// optimizationLevel: 3 //定義 PNG 圖片優化水平
    				},
    				files: [{
    					expand: true,
    					cwd: 'src/assets/images',   // 圖片在imagemin目錄下
    					src: ['**'], // 優化 imagemin 目錄下所有 png/jpg/jpeg 圖片
    					dest: 'dist/assets/images' // 優化後的圖片儲存位置,覆蓋舊圖片,並且不作提示
    				},
    				{
    					expand: true,
    					cwd: 'src/assets/fonts',   // 圖片在imagemin目錄下
    					src: ['**'], // 優化 imagemin 目錄下所有 png/jpg/jpeg 圖片
    					dest: 'dist/assets/fonts' // 優化後的圖片儲存位置,覆蓋舊圖片,並且不作提示
    				}]
    			}
    		},
    		copy: {
    		  main: {
    		    files: [{
    				expand: true,
    				cwd: 'public',
    			    src: ['**'], 
    				dest: 'dist', 
    				filter: 'isFile',
    			}],
    		  },
    		},
    		clean: {
    		  build: {
    			src: ['dist']
    		  }
    		},
    		watch: {
    			js: {
    				files: ['src/assets/scripts/*.js'],
    				tasks: ['babel']
    		    },
    		    css: {
    				files: ['src/assets/styles/*.scss'],
    				tasks: ['sass']
    			}
    		},
    		browserSync: {
    			build:{
    				open: false,
    				notify: false,
    				bsFiles: {
    				    src : ['temp', 'src', 'public']
    				},
    				options: {
    					port: 2080,
    					watchTask: true,
    				    server: {
    				        baseDir: ['temp', 'src', 'public'],
    				        routes: {
    				        	'/node_modules': 'node_modules'
    				        }
    				    }
    				}
    			}
    		},
    		useref: {
    			html: 'dist/*.html',
    			temp: 'dist'
    		},
    		htmlmin: {
    		  options: {
    			removeComments: true,
    			collapseWhitespace: true,
    			minifyCSS: true,
    			minifyJS: true,
    		  },
    		  build: {
    			expand: true,
    			cwd: 'dist',
    			src: '*.html',
    			dest: 'dist',
    		  },
    		},
    	})
    	
    	loadGruntTasks(grunt)
    	
    	grunt.registerTask('compile', ['sass','babel','swigtemplates'])
    	grunt.registerTask('htmlbuild', ['useref', 'concat', 'uglify', 'cssmin'])
    	grunt.registerTask('build', ['clean','compile','htmlbuild','copy','htmlmin','imagemin'])
    	grunt.registerTask('start', ['compile','browserSync','watch'])
    }
    

相關文章