「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
写在前面的话
在上个周突然接到一个新需求,公司有一个新项目,需要做一套H5出来,不能使用vue,原因是需要做成服务端渲染的,直接交由后端同学套模板,后端同学不会vue,我又没太多时间帮他对接口,我手里还有好几个人任务排队呢,那直能给他们来一套静态页面了,由于我也是从后端转向前端的,除了vue我也不会其他的东西呀,没办法,学呗,找博客,看看有没有轮子可以用,最开始想着用webpack,可是我不会呀,感觉又很复杂,配置了两小时。后来放弃了,继续百度看到了gulp,然后看看官网,看了一下介绍,再看看github,这不就是我想要的吗,所以就他了,搭建花费了一两个小时,之后就挺顺利的,很不错,虽然才是浅入了一下,但是成长感觉挺不错的,下次再深入一下,多用一些插件再减少人力,提高质量。
gulp
gulp 将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。
gulp是一个JavaScript工具包,用作前端Web开发中的流构建系统,基于Node.js和npm的任务运行器,用于自动化Web开发中涉及的耗时和重复性任务,gulp 使用代码配置方法来定义其任务,并依赖于其小型的单用途插件来实现它们。gulp 生态系统包括 4,298 多个这样的插件。
1. 安装引入
- 安装
npm install --global gulp-cli
- 创建项目目录
mkdir h5
- 进入目录
cd h5
- 初始化npm
npm init
- 安装gulp
npm install --save-dev gulp
- 检查版本
gulp --version
2. 开发前的准备
重点加难点
-
安装必要相关插件
插件你只需要知道怎么使用 是用来干啥的就行了,没必要每个插件都特别熟悉,了解,使用多了就自然熟悉了。
- 自动加载gulp插件的库
gulp-load-plugins - 编译sass 为 css
gulp-sass - 省时的浏览器同步工具,热加载
browser-sync - 模板工具
art-template - 处理CSS前缀问题的神器
autoprefixer - 将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件.
postcss-px-to-viewport - 删除生成目录
del - 图片压缩
gulp-imagemin - js压缩
gulp-uglify - 代理
http-proxy-middleware
- 自动加载gulp插件的库
-
创建对应的文件存放目录
├─src
│ ├─assets
│ │ ├─css
│ │ │ ├─components
│ │ │ └─mine
│ │ ├─images
│ │ │ ├─icons
│ │ ├─js
│ │ │ └─mine
│ │ └─lib
│ │ ├─swiper
│ │ ├─vant
│ │ └─vue
│ ├─layout
│ │ ├─components
│ │ └─dailog
│ └─views
│ └─mine
- src 为根目录
- assets 主要存放资源文件
- layout 存放公共模板
- views 存放html视图文件
- 尽量css、js目录对应html文件,方便查找
3. 创建gulpfile配置文件
这里我使用的 官网 的 组合任务
- 创建gulpfile.js配置文件
前期大部分时间都是花在这里,也是劝退很多人的一个地方,我都差一点点退缩了,配置一直不正确,对传统前端新人不友好。
- 引入插件
const {src, dest, parallel, series, watch} = require('gulp');
// 省时的浏览器同步工具
const browserSync = require('browser-sync');
const bs = browserSync.create();
// 自动加载gulp*插件
const loadPlugins = require('gulp-load-plugins');
const plugins = loadPlugins();
// 模板渲染
const artTemplate = require('art-template');
// css前缀
const autoprefixer = require('autoprefixer');
// 将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件.
const pxtoviewport = require('postcss-px-to-viewport');
// 删除生成目录
const clean = () => {
const del = require('del');
return del(['dist', 'temp']);
};
- css处理
因为是h5端,是要适配不同的屏幕,就使用postcss的插件来开发
// css处理
const css = () => {
return src(['src/assets/css/**'], {base: 'src'})
.pipe(plugins.if(/\.scss$/, plugins.sass()))
.pipe(
plugins.postcss([
autoprefixer({
browers: ['last 2 versions', 'ie >= 9', '> 5% in CN'],
cascade: false,
remove: false,
}),
// h5 px转vw
pxtoviewport({
// 设计稿的视口宽度
viewportWidth: 1080,
viewportHeight: 1732,
// 单位转换后保留的精度
unitPrecision: 6,
// 媒体查询里的单位是否需要转换单位
mediaQuery: true,
// 设置最小的转换数值
minPixelValue: 1,
// 忽略某些文件夹下的文件或特定文件
exclude: [/node_modules/i],
// selectorBlackList (Array) 需要忽略的CSS选择器
selectorBlackList: ['.ignore', '.hairlines', /\.van-loading__text/, /\.van-(?!loading)/],
}),
])
)
.pipe(dest('temp'))
.pipe(bs.reload({stream: true})); // 编译完成后刷新
};
- js 处理
没有特殊处理,也没有压缩
const js = () => {
return src('src/assets/js/**/*.js', {base: 'src'})
.pipe(plugins.babel({presets: ['@babel/preset-env']}))
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}));
};
- html 处理
配置时出现问题最多的地方,文件找不到了,模板语法不对了,特费神,刚上手差点就被这里劝退了,把路径控制对就没问题了
const html = () => {
// 原始语法的界定符规则,art-template 官网的
artTemplate.defaults.rules[0].test = /<%(#?)((?:==|=#|[=-])?)[ \t]*([\w\W]*?)[ \t]*(-?)%>/;
// 标准语法的界定符规则,art-template 官网的
artTemplate.defaults.rules[1].test = /<\?([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*\?>/;
// src/views/**/*.html 渲染的html文件路径
return src('src/views/**/*.html', {base: 'src'})
.pipe(
plugins.htmlTpl({
tag: 'tpl', // 勿使用这个标签<tpl>
paths: ['./src/views'], // html文件目录
engine: function (template, data) {
return (
template &&
artTemplate.compile(template, {
cache: false,
// 是否开启压缩 HTML、JS、CSS
minimize: false,
root: './src', // 根目录
})(data)
);
}
})
)
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}));
};
- 资源文件处理,可以添加文件压缩等方式处理一下,我这里没有做过多处理
// 资源文件处理
const image = () => {
return src('src/assets/images/**', {base: 'src'})
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}));
};
// 字体处理
const font = () => {
return src('src/assets/fonts/**', {base: 'src'})
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}));
};
// lib不处理
const lib = () => {
return src('src/assets/lib/**', {base: 'src'})
.pipe(dest('temp'))
.pipe(bs.reload({stream: true}));
};
// 不处理根目录下的public目录
const extra = () => {
return src('public/**', {base: 'public'})
.pipe(dest('dist'))
.pipe(bs.reload({stream: true}));
};
- 开发环境配置
配置开发监听刚才创建的处理任务
// 开发环境
const serve = () => {
watch('src/assets/css/**', css);
watch('src/assets/js/**', js);
watch('src/**/*.html', html);
watch('src/assets/lib/**', lib);
watch('src/assets/images/**', image);
watch('src/assets/fonts/**', font);
watch('public/**', extra);
bs.init({
notify: false,
port: 2080,
server: {
baseDir: ['temp', 'dist', 'src', 'public'], // 基本目录(资源文件搜索入口)
index: 'views/index.html',
// URL匹配
routes: {
'/node_modules': 'node_modules',
},
},
});
};
- 进行创建打包和调试的命令
// 使用useref处理HTML build打包合并的文件:包含js css html压缩处理
const useref = () => {
return src('temp/*.html', {base: 'temp'})
.pipe(
plugins.useref({
searchPath: ['dist', 'temp', '.'], // 匹配html中需要build的资源的路径
})
)
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(
plugins.if(
/\.html$/,
plugins.htmlmin({
minifyCSS: true, // 压缩css
minifyJS: true, // 压缩js
removeComments: true, // 清除HTML注释
})
)
)
.pipe(dest('dist'));
};
// 编译文件: 需要对文件进行处理的
const compile = parallel(css, js, html);
// 打包
const build = series(clean, lib, parallel(series(compile, useref), image, font, extra));
// 调试
const dev = series(clean, compile, serve);
module.exports = {
clean,
build,
dev,
};
- 在package.json中创建脚本命令
{
"name": "gulp-demo",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"clean": "gulp clean",
"build": "gulp build",
"dev": "gulp dev"
}
}
- 配置完成
- 创建公共头部、底部、组件,就可以像Django前后端不分离那样进行开发,接下来就是用模板形式开发减少代码重复量
<header class="search-header">
<% if ($data != 'mine') { %>
<a href="javascript:history.go(-1)" class="back-icon">
<img src="/assets/images/icons/icon23.png" alt="">
</a>
<strong class="title"><% print($data) %></strong>
<% } else { %>
<strong class="title"> </strong>
<% } %>
<a href="javascript:">
<img src="/assets/images/icons/icon8.png" alt="">
</a>
</header>
- view中的文件引入公共文件
<% include('./layout/header.html', 'index') %>
结语
我是幸福部长,我在学gulp了,已经使用gulp完成了一个h5项目,总的来说除了刚开始搭建项目时,配置有一点困难,其他的都还好,速度很快。