前端工程化解決的問(wèn)題:
- 傳統(tǒng)語(yǔ)言或語(yǔ)法的弊端 ;
- 無(wú)法使用模塊化/組件化
- 重復(fù)的機(jī)械式工作
- 代碼風(fēng)格統(tǒng)一、質(zhì)量保證
- 依賴后端服務(wù)接口支持
- 整體依賴后端項(xiàng)目
腳手架工具
腳手架本質(zhì)作用:創(chuàng)建項(xiàng)目基礎(chǔ)結(jié)構(gòu)蜗元、提供項(xiàng)目規(guī)范和約定
- 相同的組織結(jié)構(gòu)
- 相同的開(kāi)發(fā)范式
- 相同的模塊依賴
- 相同的工具配置
- 相同的基礎(chǔ)代碼
步驟:
- 在全部范圍安裝yo
npm install yo --global or yarn global add yo
- 安裝對(duì)應(yīng)的generator
npm install generator-node or yarn global add genertor-node
- 安裝yo運(yùn)行g(shù)enerator
yo node
yeoman的常規(guī)使用步驟
- 明確你的需求
- 找到合適的Generator
- 全局范圍安裝找到的Generator
- 通過(guò)Yo運(yùn)行對(duì)應(yīng)的Generator
- 通過(guò)命令行交互填寫選項(xiàng)
- 生成你所需要的項(xiàng)目結(jié)構(gòu)
自定義Generator
Generator基本結(jié)構(gòu)
index.js1
index.js2
Plop
小而美的腳手架
- 將plop模塊作為項(xiàng)目開(kāi)發(fā)依賴
- 在項(xiàng)目根目錄下創(chuàng)建一個(gè)plopfile.js文件
- 在plopfile.js文件中定義腳手架任務(wù)
- 編寫用于生成特定類型文件的模板
-
通過(guò)Plop提供的CLI運(yùn)行腳手架任務(wù)
plop應(yīng)用文件
自動(dòng)化構(gòu)建工具
grunt 的基本使用:
gruntfile.js 文件
module.exports = grunt => {
grunt.registerTask('foo', () => {
console.log('hello grunt~')
})
grunt.registerTask('bar', '任務(wù)描述', () => {
console.log('other task~')
})
grunt.registerTask('default', ['foo', 'bar'])
// grunt.registerTask('async-task', () => {
// setTimeout(() => {
// console.log('async task working~')
// }, 1000)
// })
grunt.registerTask('async-task', function () {
const done = this.async()
setTimeout(() => {
console.log('async task working~')
done(false) //標(biāo)記任務(wù)失敗
}, 1000)
})
}
grunt的配置
module.exports = grunt => {
grunt.initConfig({
foo: {
bar: 123
}
})
grunt.registerTask('foo', () => {
console.log(grunt.config('foo'))
})
}
grunt 的多目標(biāo)任務(wù)
module.exports = grunt => {
grunt.initConfig({
build:{
options: {
foo: 'bar'
},
css: {
options: {
foo: 'baz'
}
},
js: '2'
}
})
//多目標(biāo)模式傻咖,可以讓任務(wù)根據(jù)配置形成多個(gè)子任務(wù)
grunt.registerMultiTask('build', function () {
console.log(this.options())
console.log(`target: ${this.target}, data: ${this.data}`)
})
}
grunt 的插件的使用
- 導(dǎo)入插件模塊
- 然后使用
grunt.loadNpmTasks()
創(chuàng)建插件任務(wù) - 在
initConfig()
中配置選項(xiàng)
插件使用
grunt 使用案例
const sass = require('sass')
const loadGruntTasks = require('load-grunt-tasks')
module.exports = grunt => {
grunt.initConfig({
sass: {
options: {
sourceMap: true,
implementation: sass
},
main: {
files: {
'dist/css/main.css': 'src/scss/main.scss'
}
}
},
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env']
},
main: {
files: {
'dist/js/app.js': 'src/js/main.js'
}
}
},
watch: {
js: {
files: ['src/js/*.js'],
task: ['babel']
},
css: {
files: ['src/scss/*.scss'],
tasks: ['sass']
}
}
})
//自動(dòng)加載所有g(shù)runt 插件任務(wù)
loadGruntTasks(grunt)
grunt.registerTask('default', ['sass', 'babel', 'watch'])
// grunt.loadNpmTasks('grunt-sass')
}
gulp
gulpfile.js
exports.foo = (done) => {
console.log('foo task working~')
done() //回調(diào)函數(shù)它碎,標(biāo)識(shí)任務(wù)完成
}
exports.default = (done) => {
console.log('default task working~')
done() //回調(diào)函數(shù)刘急,標(biāo)識(shí)任務(wù)完成
}
gulp的組合任務(wù)
const {series, parallel} = require('gulp')
const task1 = done => {
setTimeout(()=> {
console.log('task1 working')
done()
}, 1000)
}
const task2 = done => {
setTimeout(()=> {
console.log('task2 working')
done()
}, 1000)
}
const task3 = done => {
setTimeout(()=> {
console.log('task3 working')
done()
}, 1000)
}
exports.foo = series(task1, task2, task3) //串行執(zhí)行任務(wù)
exports.bar = parallel(task1, task2, task3) //并行執(zhí)行任務(wù)
gulp文件操作API
const {src, dest} = require('gulp')
const cleanCss = require('gulp-clean-css')
const rename = require('gulp-rename')
exports.default = () => {
return src('src/*.css')
.pipe(cleanCss())
.pipe(rename({extname: '.min.css'}))
.pipe(dest('dist'))
}
gulp-demo
const { src, dest, parallel, series, watch } = require('gulp')
const del = require('del')
const browserSync = require('browser-sync')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
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(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 } })) // 防止模板緩存導(dǎo)致頁(yè)面不能及時(shí)更新
.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 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/**',
server: {
baseDir: ['temp', 'src', 'public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
const useref = () => {
return src('temp/*.html', { base: 'temp' })
.pipe(plugins.useref({ searchPath: ['temp', '.'] }))
// html js css
.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 compile = parallel(style, script, page)
// 上線之前執(zhí)行的任務(wù)
const build = series(
clean,
parallel(
series(compile, useref),
image,
font,
extra
)
)
const develop = series(compile, serve)
module.exports = {
clean,
build,
develop
}