一、前端工程化
1.1 工程化的定义和主要解决的问题
前端工程化:是指遵循一定的标准和规范通过工具去提高效率,降低成本的一种手段
主要解决的问题:
1. 传统语言或语法的弊端
2. 无法使用模块化/组件化
3. 重复的机械式工作
4. 代码风格统一、质量保证
5. 依赖后端服务接口支持
6. 整体依赖后端项目
1.2 一个项目 过程中工程化的表现
一切重读的工作都应该被自动化
创建项目-------->编码----------->预览/测试----------->提交------->部署
1.3 工程化不等于工具
工具并不似工程化的核心,工程化的核心应该是对整体项目的规划或者架构,工具只是让 我们实现规划或者架构的一种手段
1.4 工程化与Node.js
node.js是前端的基础,蕨功至韦的node.js
二、脚手架工具
2.1 脚手架工具描述
脚手架的本质作用:自动创建项目基础结构、提供项目规范和约定
相同的组织结构,开发范式,模块依赖,工具配置,基础代码都可以用脚手架进行配置
2.2 常用的脚手架工具
react项目 ------> create-react-app
vue项目 ------> vue-cli
Angular项目 -----> angular-cli
以上都是根据信息创建对应的项目基础结构
Yeoman: 通过性脚手结构
Plop: 开发过程中创建特定类型的文件,列如创建一个组件/模块所需要的文件
2.3 Yeoman 简介
Yeoman是用于创造现代化web应用的脚手架工具,更像脚手架平台
2.4 Yeoman 基础使用
// npm 安装 Yeoman // yo就是Yeoman的缩写 //案例: 用generator 生成node
1\. npm install yo --global 在全局范围安装 yo
2\. npm install generator-node --global // 安装对应得generator
3\. yo node // 到要搭建得项目里输入yo
// yarn 安装Yeoman
1\. yarn global add yo
// yeoman 要搭配专门的generator才能去使用,如果想使用node模块就是用generator-node 这个模块
// 2\. yarn global add generator-node
mkdir my-module // 创建my-module 文件夹
// 3\. yo node // 到要搭建得项目里输入yo 3.1\. Module Name://你的模块叫什么名字------回车
3.2\. The name above already on npm,choose another (y/n): //已经存在名字,是否换 ----no
3.3 Description:// ‘项目描述’
3.4 Project homepage url: //项目主页 可以找一个github网址写进去
4.4 Autor's Name: // 回车//自动填(建议),或者自己输入名字
4.5 Autor's Email // 回车 // email地址
4.6 Autor's Homepage // 回车 // 主页
4.7 Package keywords (comma to split) // 输入关键字,多个关键字用逗号隔开
4.8 Send coverage reports to coveralls (Y/n) // 是否发代码覆盖率到某一个网站上 // n
4.9 Enter Node versions // 支持哪个版本node // 回车 自动支持所有版本
5.0 GitHub username or organization // 输入github 用户名
5.1 Which license do you want to use // 选择基础结构 // 选择 Mit
5.2 // 可能会卡死 ,直接回车就行了
2.5 Sub Generator
yo node:cli
1. 提示是否重写 ----y
2. yarn link
3. yarn istall
4. my-module --help
2.6 Yeoman 使用步骤总结
1. 明确你的需求
2. 找到合适得Generator
3. 全局范围安装找到的 Generator
4. 通过Yo 运行对应的Generator
5. 通过命令行交互填写选项
6. 生成你所需要的项目结构
例: 1. yarn global add generator-webapp
2. yo webapp (选sass)
2.7 自定义Generator
1\. yarn init 创建json文件
2\.
2.8 创建Generator 模块
// 首先,创建一个文件夹,在其中编写发电机,必须命名此文件夹generator-name(name生成器的名称在此处)。这一点很重要,因为Yeoman依靠文件系统来查找可用的生成器
1. yarn init
2. yarn add yeoman-generator
// 此文件作为Generator 的核心入口,需要导出一个继承自Yeoman Generator 的类型
// yeoman generator 在工作时会自动调用我们在此类型中的定义的一些生命周期函数
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,列如 文件写入
3. 文件里创建一个app/index.vue 的文件并写一个简单的模块
4. yarn link // 把模块链接到全局范围,是他成为一个全局模块包
5. 在外部创建一个新的文件夹my-demo
6. 在新创建的文件夹中运行 yo name (name 是上一个文件 generator-name 后缀名字)
2.9 根据模板创建文件
相对于手动创建每一个文件,模板的方式大大提高了效率
2.10 接收用户输入
// 接口用户的动态输入列如标题,这种一般通过命令行交互的方式去询问使用者,从而得到
// 发起命令行交互的询问可以用generator中的 prompting()方法
2.11 Vue Generator 案例
在桌面创建文件夹generator-vueCreater
1\. yarn init
2\. yarn add yeoman-generator
3\. 创建文件index.js 和一个文件夹里面放入初始化的vue项目
5\. 在vue里的 package.json、 README.md 和 index.html里面将name、标题和title 换成<%= name%>
4\. yarn link
5\. yo vueCreater
ps: <%= name%> ejs 模板的标记
2.12 发布Generator
generator 就是一个npm模块,发布generator就是发布一个模块,通过npm publish 发布成公开模块
// 先创建本地仓库
1. echo node_modules > .gitignore // 先创建gitignore 来忽略node_modules
2. git init // 初始化本地的一个空仓库
3. git status // 本地仓库的状态
4. git add . // 跟踪当前目录下文件
5. git commit -m '' // 提交
6. 同步到 远程仓库 git remote add origin https://github.com/wangxiang-1/difficulty.git //为本地仓库添加一个远程仓库的别名
7. git push -u origin master// push时使用这个别名
ps: 注意事项:
1. 把源切换成 npm config set registry http://registry.npmjs.org 不要使用淘宝源
2. 需要输入或者登录npm的账号,npm login 8. npm publish // 用publish 发布这个模块 也可以用yarn publish 发布,效果是一样的
2.13 Plop 简介
// 小而美的脚手架工具
yarn plop component // 自动构建一些文件
2.14 Plop 的基本使用
// 案列: 建议使用npm的版本大于5.2创建
首先在一个空文件夹中创建一个名为my-app的react项目:npx create-react-app my-app
npm start 运行
1. 新建一个plopfile.js文件
2. npm i plop --dev 安装plop
3. 创建一个plopfile.js文件并在文件中定义脚手架任务
4. 编写用于生成特定类型文件的模板
5. yarn plop component // component 是生成器的名字
代码:
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', // 指定添加到的路径,{{name}} 可以用插值表达式来获取上面输入的路径 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' } ] })}
2.15 脚手架的工作原理
脚手架工具就是node cli应用
1\. yarn init
2\. 在生成的package.json文件中添加一个bin:"cli.js"; 用来添加 cli的入口文件
3\. cli.js里面先用console一段字做测试
4\. yarn link
5\. sample-scaffolding // 运行 项目的name名称 如果打印说明cli应用的基础就可以了
6\. yarn add inquirer
7\. yarn add ejs
三、自动化构建
3.1 自动化构建简介
一切重复工作本应自动化
构建:转化
自动化:通过机器代替手工完成一定的工作 自动化构建:相当于把开发的源代码自动化构建成生产代码 // 一般称为自动化构建工作流 作用:尽可能脱离运行环境兼容带来的问题,使用提高效率的语法、规范和标准 // es6 sass 模板引擎
3.2 自动化构建初体验
1. yarn init
2. yarn add sass --dev
3 找到模块里sass的路径 .\node_modules\.bin\sass
// scss/main.scss 是输入路径 css/style.css为生成的输出路径
4. .\node_modules\.bin\sass scss/main.scss css/style.css
// 以上缺点:每次需要重复输入命令
npm Scripts能解决上面的问题,他是实现自动化构建做东流的最简方式
1. 在package.json里添加
"scripts": { "build":"sass scss/main.scss css/style.css" },
2. yarn build 3. yarn add browser-sync --dev //用于启用一个测试服务器来运行项目
"scripts": { "build":"sass scss/main.scss css/style.css", "serve": "browser-sync ." //在json里添加serve 用来运行它 },
4. yarn serve // 注意: 如果在yarn serve运行时并没有 生成css/style.css文件的样式就需要加一段
"scripts": { "build": "sass scss/main.scss css/style.css", "preserve": "yarn build", // 使用preserve 使项目在运行前先yarn build 生成css文件 "serve": "browser-sync ." },
// 如何监听scss"scripts": { "build": "sass scss/main.scss css/style.css --watch", // watch 会监听scss "preserve": "yarn build", // 使用preserve 使项目在运行前先yarn build 生成css文件 "serve": "browser-sync ." },
// 注意: 只使用watch,运行后会阻塞在sass来监听sass的变化
// 解决: npm add npm-run-all --dev //配合用来监听所有变化
"scripts": { "build": "sass scss/main.scss css/style.css --watch", "serve": "browser-sync .", "start": "run-p build serve" // 添加start 同时运行run-p build serve 三个命令 },
yarn start
// 如何监听文件变化
"serve": "browser-sync . --files \"css/*.css\"", // 监听css
3.3 常用的自动化构建工具
1. Grunt 2. Gulp 3. FIS
Grunt: 最早的构建工具; 由于它工作过程是基于临时文件去实现的,构建速度较慢
Gulp: 基于内存实现的,构建速度快,默认支持同时执行多个任务,主流
FIS: 百度的前端团队构建的系统,开源后快速流行;微内核的特点,它更像
捆绑套餐,它把开发中典型的需求尽可能集成在内部
3.4 Grunt 的基本使用
1. yarn init --yes
2. yarn add grunt
// 添加一个grunt的入口文件,用于定义一些grunt 自动执行的任务,需要导出一个函数
此函数接收一个grunt的形式参数,内部提供一些创建任务时可以用到的API
3. code gruntfile.js
4. 运行:yarn grunt name; // name是第一个参数的名称
重点
3.5 Grunt 标记任务失败
3.6 Grunt 的配置方法
使用grunt.initConfig()方法配置
3.7 Grunt 多目标任务
3.8 Grunt 插件的使用
插件机制是grunt的核心
1. yarn add grunt-contrib-clean //它可以自动清除项目在开发过程中的临时文件
3.9 Grunt 常用插件及总结
1. grunt-sass
yarn add grunt-sass sass --dev
grunt-sass的基本用法
yarn add grunt-babel @babel/core @babel/perset-env --dev
yarn add load-gunt-tasks --dev // 安装多个模块时,为减少loadNpmTasks的使用可以安装此模块
yarn add grunt-contrib-watch --dev // 文件修改完成后需要自动构建的话,就需要这个插件
yarn grunt watch // 添加完监听后,可以运行,查看效果
// 如果使用registerTask用default,可以执行yarn grunt
3.10 Gulp 的基本使用
gulp 主流前端构建系统 // 需要创建一个 gulpile.js 文件
yarn add gulp --dev // 安装gulp
// Gulp的入口文件,是通过导出函数成员的方式去定义
code gulpfile.js // 在vscode 中创建 gulpfiles.js ,
3.11 Gulp 的组合任务
通过 series, parallel 将多个任务合成一个组合任务
3.12 Gulp 的异步任务
异步任务的三种方式:
const fs = require('fs')exports.callback = done => { console.log('callback task') done()}// 会有错误优先.报错后会阻止后续任务的工作exports.callback_error = done => { console.log('callback task') done(new Error('错误'))}// promise避免回调嵌套过深的问题exports.promise = () => { console.log('promise task') return Promise.resolve() // return 一个成功的对象}// promise失败的任务,同样会结束后面的代码运行exports.promise_error = () => { console.log('promise task') return Promise.reject(new Error('task failed'))}// async await 是promise的语法糖// 让使用promise的代码更加容易理解const timeout = time => { return new Promise(resolve => { setTimeout(resolve, time) })}exports.async = async () => { await timeout(1000) console.log('async task')}// exports.stream = () => { // 需要返回一个stream对象 const read = fs.createReadStream('yarn.lock') // fs.createReadStream读取文件的文件流 const write = fs.createWriteStream('a.txt') // 写入的文件流 read.pipe(write) // 把write导入到read里 return read}exports.stream = done => { const read = fs.createReadStream('yarn.lock') const write = fs.createWriteStream('a.txt') read.pipe(write) read.on('end', () => { // 有一个end事件可以监听任务结束的事件 done() })}
3.13 Gulp 构建过程核心工作原理
输入(读取流)=> 加工(转换流) => 输出(写入流)
gulp的官方定义就是 The streaming build system :基于流的构建系统
为什么构建过程中选择流的方式,是因为gulp希望实现一个构建管道的概念,后续做扩展插件时就可以有一个很统一的方式
3.14 Gulp文件操作API
通过src 去pipe一个插件转化流,再pipe到一个写入流这样的过程,就是gulp的常规过程
3.15 Gulp 案例 - 样式编译
1\. yarn add gulp --dev
2\. yarn add gulp-sass --dev // sass转换css
gitee.com地址:https://gitee.com/wx19960912/task-wx/tree/master/part2-01/02-01-study-materials/code/02-01-03-12-zce-gulp-demo
3.16 Gulp 案例 - 脚本编译
3\. yarn add gulp-babel --dev
const { src, dest, parallel, series, watch } = require('gulp')const sass = require('gulp-sass')const babel = require('gulp-babel')const script = () => { return src('src/assets/scripts/*.js', { base: 'src' }) // .pipe(babel()) // 报错是少模块进行转换 // 需要手动安装yarn add @babel/core @babel/preset-env --dev // 会把所有最新的es6进行转换 .pipe(babel({ presets: ['@babel/preset-env'] })) // 最新特性的所有打包 .pipe(dest('dist'))}
module.exports = { script}// 运行 yarn gulp script
3.17 Gulp 案例 - 页面模板编译
4\. yarn add gulp-swig -- dev // 页面模板可以重用html文件
const { src, dest, parallel, series, watch } = require('gulp')const sass = require('gulp-sass')const babel = require('gulp-babel')const swig = require('gulp-swig')
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' }) // base 设置基准路径 .pipe(sass({ outputStyle: 'expanded' })) .pipe(dest('dist')) }const script = () => { return src('src/assets/scripts/*.js', { base: 'src' }) // 需要手动安装yarn add @babel/core @babel/preset-env --dev // 会把所有最新的es6进行转换 .pipe(babel({ presets: ['@babel/preset-env'] })) // 最新特性的所有打包 .pipe(dest('dist'))}const page = () => { // return src('src/**/*.html') // 匹配src下面所有html文件 return src('src/*.html', { base: 'src' }) // 防止模板缓存导致页面不能及时更新
.pipe(swig({ data }))
.pipe(dest('temp'))}
const compile = parallel(style, script, page) // 使用组合的模式,parallel同时调用module.exports = { compile }// 运行 yarn gulp compile
3.18 Gulp 案例 - 图片和字体文件转换
5\. yarn add imagemin --dev ;imagemin 是通过c++ 完成的模块,需要下载二进制的程序集
const imagemin = require('gulp-imagemin') 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'))}
const compile = parallel(image,font)module.exports = { compile}// 运行yarn gulp compile
3.19 Gulp 案例 - 其他文件及文件清理
const extra = () => { return src('public/**', { base: 'public' }) .pipe(dest('dist'))}
const compile = parallel(style, script, page,image,font)
// 上线之前执行的任务const build = parallel( compile, extra )
module.exports = { build }// 自动清除dist下目录文件
6\. yarn add del --dev
// series 需要异步执行否则上面执行的文件被删除的情况
const {parallel, series } = require('gulp') const del = require('del')const clean = () => { return del(['dist']) //路径}const compile = parallel(style, script, page, image, font)const build = series( // 需要异步执行,先删除之前的dist文件,然后再加载新的 clean, parallel( compile, extra ))module.exports = { build}
3.20 Gulp 案例 - 自动加载插件
7\. yarn add gulp-load-plugins --dev
const loadPlugins = require('gulp-load-plugins')const plugins = loadPlugins()
//简便方法的小操作,babel,imagemin也是同样的操作
// 选中sass ,按F2 ,重命名位plugins.sass ,下面的引入也会被修改
// 然后把const sass = require('gulp-sass') 删了就行//const sass = require('gulp-sass')
3.21 Gulp 案例 - 开发服务器
8. yarn add browser-sync --dev
browser-sync 它支持代码修改过后自动热更新到浏览器中
// 他会自动创建一个开发服务器
const browserSync = require('browser-sync')
const bs = browserSync.create()const serve = () => { bs.init({ notify: false, // 关掉项目运行时浏览器一开始提示browserSync是否已连接 port: 2080, // 端口 // open: false, // 取消自动打开浏览器 files: 'dist/**', // 被browserSync监听的文件 server: { baseDir: ['dist'], //设置网页根目录 routes: { // 指定依赖,会比上一步先指定 '/node_modules': 'node_modules' } } })}
module.exports = { serve}
// 此步骤是当dist文件变化时,浏览器自动更新
3.22 Gulp 案例 - 监视变化以及构建优化
// 此步骤当src变化后,会自动编译
watch
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 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'])}const style = () => { return src('src/assets/styles/*.scss', { base: 'src' }) // base 设置基准路径 // 转化后每个样式最后一个括号,连在样式后面,没有换行,使用outputStyle: 'expanded'使其放在空行 .pipe(plugins.sass({ outputStyle: 'expanded' })) .pipe(dest('dist')) .pipe(bs.reload({ stream: true })) // 默认把文件流的信息推送到浏览器}const script = () => { return src('src/assets/scripts/*.js', { base: 'src' }) // 需要手动安装yarn add @babel/core @babel/preset-env --dev // 会把所有最新的es6进行转换,最新特性的所有打包 .pipe(plugins.babel({ presets: ['@babel/preset-env'] })) .pipe(dest('dist')) .pipe(bs.reload({ stream: true })) // 默认把文件流的信息推送到浏览器}const page = () => { return src('src/*.html', { base: 'src' }) // 防止模板缓存导致页面不能及时更新 .pipe(plugins.swig({ data, defaults: { cache: false } })) .pipe(dest('dist')) .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 指定两个参数,第一个是监听源文件路径,第二个是指定的任务函数 watch('src/assets/styles/*.scss', style) watch('src/assets/scripts/*.js', script) watch('src/*.html', page)
// 因为 image,font这些只需要再打包到dist时压缩一下就行,当在开发时启动会降低编译速度 // watch('src/assets/images/**', image) // watch('src/assets/fonts/**', font) // watch('public/**', extra) // 如果新增图片,字体也想更新浏览器,用一个watch ,减少构建次数 // reload方法地址: http://www.browsersync.cn/docs/api/#api-reload
// 该 reload 方法会通知所有的浏览器相关文件被改动,要么导致浏览器刷新,要么注入文件,实时更新改动。 watch([ 'src/assets/images/**', 'src/assets/fonts/**', 'public/**' ], bs.reload) bs.init({ notify: false, // 关掉项目运行时浏览器一开始提示browserSync是否已连接 port: 2080, // 端口 // open: false, // 取消自动打开浏览器 // files: 'dist/**', // 被browserSync监听的文件 server: { //设置网页根目录 ,当dist文件没有指定文件时,会往后找,提高构建效率 baseDir: ['dist', 'src', 'public'], routes: { // 指定依赖,会比上一步先指定 '/node_modules': 'node_modules' } } })}// 开发时执行的任务const compile = parallel(style, script, page)// 上线之前执行的任务 打包const build = series( clean, parallel( compile, image, font, extra ))const develop = series(compile, serve)module.exports = { clean, build, serve, develop}
3.23 Gulp 案例 - useref 文件引用处理
9\. yarn add gulp-useref --dev // useref的意思的引用关系
// 自动处理index.heml 的引入注释const useref = () => { return src('dist/*.html', { base: 'dist' }) // 把构建注释做一个转换, .pipe(plugins.useref({ searchPath: ['dist', '.'] })) .pipe(dest('dist'))}module.exports = { useref}// yarn gulp useref
把所有引入css文件合并到一个文件中,或则把多个js文件合并到一个文件中
3.24 Gulp 案例 - 文件压缩
10\. yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
// 安装 html,js和css的压缩插件
11\. yarn add gulf-if --dev
// 安装插件判断读取的是什么文件
const useref = () => { return src('dist/*.html', { base: 'dist' }) // 把构建注释做一个转换, .pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 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, // 去掉html中css 的空白字符和换行符 minifyJS: true // 同上 }))) .pipe(dest('dist'))
// 如果dist里 css样式主文件是空的,可以.pipe(dest('temp')) 生成一个新文件}
3.25 Gulp 案例 - 重新规划构建过程
把编译的文件先放到一个临时的文件中
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 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 } })) .pipe(dest('temp')) // 放在临时文件 .pipe(bs.reload({ stream: true }))}const image = () => { return src('src/assets/images/**', { base: 'src' }) .pipe(plugins.imagemin()) .pipe(dest('dist')) // 不用放在临时目录,因为它只是在build时放在dist文件中}const font = () => { return src('src/assets/fonts/**', { base: 'src' }) .pipe(plugins.imagemin()) .pipe(dest('dist')) // 不用放在临时目录,因为它只是在build时放在dist文件中}// 其他文件const extra = () => { return src('public/**', { base: 'public' }) .pipe(dest('dist')) }const serve = () => { // watch 指定两个参数,第一个是监听源文件路径,第二个是指定的任务函数 watch('src/assets/styles/*.scss', style) watch('src/assets/scripts/*.js', script) watch('src/*.html', page) watch([ 'src/assets/images/**', 'src/assets/fonts/**', 'public/**' ], bs.reload) bs.init({ notify: false, // 关掉项目运行时浏览器一开始提示browserSync是否已连接 port: 2080, // 端口 server: { //设置网页根目录 ,当dist文件没有指定文件时,会往后找,提高构建效率 baseDir: ['temp', 'src', 'public'], routes: { // 指定依赖,会比上一步先指定 '/node_modules': 'node_modules' } } })}
// 自动处理index.heml 的引入注释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 }))) // 如果dist里 css样式主文件是空的,可以.pipe(dest('temp')) 生成一个新文件 .pipe(dest('dist'))}// 开发时执行的任务const compile = parallel(style, script, page)// 上线之前执行的任务 打包const build = series( clean, parallel( series(compile, useref), // compile 必须先执行才能执行useref image, font, extra ))const develop = series(compile, serve)module.exports = { build, serve, develop,}
3.26 Gulp 案例 - 补充
ctrl +k && ctrl + 1 把项目折叠隐藏到最高层
module.exports = { // 只暴露出 三个组合任务就够了 clean, build, develop,}
3.27 封装工作流 - 准备
gulpfile的复用问题,在开发多个同样的应用的时候可以复用
gulpfile + Gulp = 构建工作流
3.28 封装工作流 - 提取gulpfile
1. 先创建一个新的项目:事列代码地址:gitee.com/wx19960912/…
2.修改配置
3. yarn link 将其link 到全局
4. 在一个新的项目中 yarn link 'name' ,link完node_modules 下会出现link的文件
4. 安装 gulp 合gulp-cli 并且添加 page.config.js文件
5. 在根目录下添加gulpfile.js 入口文件 引用 link的项目
6. 根据pageage.json里的配置运行或者打包此项目 yarn build
3.29 封装工作流 - 解决模块中的问题
增加在源配置中增加 build 配置,并把gulpfile.js里所有路径都引用配置里的路径
3.30 封装工作流 - 抽象路径配置
在源文件中使用cli的方式添加
3.31 封装工作流 - 包装Gulp Cli
配置bin里 zce-pages.js, 重新link一下: yarn link : 之前link 过需要注销 一下 yarn unlink
3.32 封装工作流 - 发布并使用模块
1. yarn pubilsh 发布到npm