上传文件至 /
This commit is contained in:
commit
9d32fc9a9b
|
@ -0,0 +1,37 @@
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
采用 Gulp 4.0.2 搭建的 js 自动构建任务项目
|
||||||
|
|
||||||
|
## 安装使用
|
||||||
|
|
||||||
|
请先安装**Node 14 和 Npm**,安装过程略过。
|
||||||
|
|
||||||
|
- 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm i
|
||||||
|
```
|
||||||
|
|
||||||
|
- 运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
- 打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 目录介绍
|
||||||
|
|
||||||
|
- dist:打包结果目录
|
||||||
|
- src:源码目录
|
||||||
|
- src/modules:公共 html 目录,此目录的 html 不会出现在打包结果中,此目录的 html 中引入 css 或者 js,请使用绝对路径,如/js/xxx.js /css/xxx.css,其他资源,如图片也是如此
|
||||||
|
- src/css:css 源码
|
||||||
|
- src/js:js 源码
|
||||||
|
- src/static:静态文件,如第三方库,第三方样式等可以放在此处,打包时不会进入文件转换流程,会直接复制到打包结果中
|
||||||
|
- src/index.html:网站入口
|
||||||
|
- config.js:打包配置
|
||||||
|
- gulpfile.js:gulp 构建流程
|
|
@ -0,0 +1,31 @@
|
||||||
|
export default {
|
||||||
|
// 用于代码替换,key为文件id,value内容所在文件路径,为绝对路径,/为根目录
|
||||||
|
// 在html中使用#include函数引入,如#include(navbar)
|
||||||
|
moduleMap: {
|
||||||
|
'navbar': '/src/modules/navbar.html',
|
||||||
|
"footer": '/src/modules/footer.html',
|
||||||
|
},
|
||||||
|
assetsDir: "dist",
|
||||||
|
devServer: {
|
||||||
|
// 详情配置请看 https://www.npmjs.com/package/http-proxy-middleware#options
|
||||||
|
httpProxy: {
|
||||||
|
// "/api": {
|
||||||
|
// target: '', // 替换为你的后端服务器地址
|
||||||
|
// changeOrigin: true, // 如果需要的话,改变请求的origin
|
||||||
|
// pathRewrite: {
|
||||||
|
// '^/api': '' // 移除请求中的/api前缀
|
||||||
|
// },
|
||||||
|
// logLevel: "debug"
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
// 详情配置请看 https://browsersync.io/docs/options#option-server middleware和server不可配置
|
||||||
|
browsersync: {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 3000,
|
||||||
|
open: true,
|
||||||
|
ui: {
|
||||||
|
port: 3001
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,273 @@
|
||||||
|
import gulp from "gulp";
|
||||||
|
import gulpIf from "gulp-if";
|
||||||
|
import MemoryFS from "memory-fs";
|
||||||
|
import syncBrowser from "browser-sync";
|
||||||
|
const browserSync = syncBrowser.create();
|
||||||
|
const __dirname = process.cwd();
|
||||||
|
|
||||||
|
// 创建内存文件系统实例
|
||||||
|
const mfs = new MemoryFS();
|
||||||
|
import htmlmin from "gulp-htmlmin"; // 压缩html文件
|
||||||
|
import uglify from "gulp-uglify"; // 压缩js文件
|
||||||
|
import babel from "gulp-babel"; // ES6转ES5
|
||||||
|
import sass from "gulp-sass"; // sass编译
|
||||||
|
import cleanCss from "gulp-clean-css"; // 压缩css文件
|
||||||
|
import replace from "gulp-replace"; // 替换文件内容
|
||||||
|
import ignore from "gulp-ignore"; // 排除文件不进入打包结果
|
||||||
|
import { deleteAsync } from "del"; // 清除打包目标目录
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
import map from "map-stream";
|
||||||
|
import { createProxyMiddleware } from "http-proxy-middleware";
|
||||||
|
|
||||||
|
const devAssetsDir = "src";
|
||||||
|
const htmlGlob = `${devAssetsDir}/**/*.html`;
|
||||||
|
const cssGlob = `${devAssetsDir}/**/*.css`;
|
||||||
|
const jsGlob = `${devAssetsDir}/**/*.js`;
|
||||||
|
const staticGlob = `${devAssetsDir}/static/**/*`;
|
||||||
|
const modulesGlob = "modules/**/*";
|
||||||
|
const allFileGlob = `${devAssetsDir}/**/*`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {"dev" | "prod"} 环境变量
|
||||||
|
*/
|
||||||
|
let env = "dev";
|
||||||
|
function setEnv(currEnv) {
|
||||||
|
return async () => {
|
||||||
|
env = currEnv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
import config from "./config.js";
|
||||||
|
let { moduleMap, assetsDir, devServer } = config;
|
||||||
|
let { browsersync: browsersyncOptions, httpProxy } = devServer && typeof devServer === "object" ? devServer : {};
|
||||||
|
moduleMap = parseModuleMap(moduleMap);
|
||||||
|
// 异步读取文件内容
|
||||||
|
async function getCode(path) {
|
||||||
|
return await fs.readFile(path, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除dist目录的任务
|
||||||
|
async function cleanTask() {
|
||||||
|
return deleteAsync([assetsDir]); // 使用 del 删除 dist 目录及其内容
|
||||||
|
}
|
||||||
|
|
||||||
|
export const clean = cleanTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 注入模块
|
||||||
|
* @param {NodeJS.ReadWriteStream} ctx
|
||||||
|
* @returns {NodeJS.ReadWriteStream}
|
||||||
|
*/
|
||||||
|
async function injectModules(ctx) {
|
||||||
|
// 遍历模块文件,将每个模块文件的内容替换到对应的模块标签中
|
||||||
|
for (const key in moduleMap) {
|
||||||
|
const filePath = path.join(__dirname, moduleMap[key]);
|
||||||
|
const code = await getCode(filePath);
|
||||||
|
const replaceStream = replace(key, code);
|
||||||
|
ctx = ctx.pipe(replaceStream);
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 制定html任务
|
||||||
|
async function htmlTask() {
|
||||||
|
const condition = env === "prod";
|
||||||
|
let ctx = gulp.src(htmlGlob, {
|
||||||
|
ignore: [staticGlob],
|
||||||
|
});
|
||||||
|
ctx = await injectModules(ctx);
|
||||||
|
return (
|
||||||
|
ctx
|
||||||
|
.pipe(
|
||||||
|
htmlmin({
|
||||||
|
removeComments: condition, // 生产环境下移除注释
|
||||||
|
collapseWhitespace: condition, // //压缩HTML
|
||||||
|
collapseBooleanAttributes: condition, //省略布尔属性的值 <input checked="true"/> ==> <input />
|
||||||
|
removeEmptyAttributes: env === "prod", //删除所有空格作属性值 <input id="" /> ==> <input />
|
||||||
|
removeScriptTypeAttributes: false, //删除<script>的type="text/javascript"
|
||||||
|
removeStyleLinkTypeAttributes: condition, //删除<style>和<link>的type="text/css"
|
||||||
|
minifyJS: condition, //压缩页面JS
|
||||||
|
minifyCSS: condition, //压缩页面CSS
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(ignore.exclude(modulesGlob)) // 忽略模块文件
|
||||||
|
.pipe(gulpIf(condition, writeFileToFileSystem(assetsDir)))
|
||||||
|
// 将处理后的文件写入内存文件系统
|
||||||
|
.pipe(gulpIf(!condition, writeFileToMemory()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义Gulp任务
|
||||||
|
export const html = htmlTask;
|
||||||
|
|
||||||
|
// 制定js任务:ES6转ES5,再压缩js
|
||||||
|
async function jsTask() {
|
||||||
|
const ctx = gulp.src(jsGlob, {
|
||||||
|
ignore: [staticGlob],
|
||||||
|
});
|
||||||
|
const condition = env === "prod";
|
||||||
|
return ctx
|
||||||
|
.pipe(
|
||||||
|
gulpIf(
|
||||||
|
condition,
|
||||||
|
babel({
|
||||||
|
presets: ["@babel/preset-env"],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
gulpIf(
|
||||||
|
condition,
|
||||||
|
uglify({
|
||||||
|
compress: {
|
||||||
|
drop_console: false, // 移除console语句
|
||||||
|
drop_debugger: true, // 移除debugger语句
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.pipe(gulpIf(condition, writeFileToFileSystem(path.join(assetsDir))))
|
||||||
|
.pipe(gulpIf(!condition, writeFileToMemory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const js = jsTask;
|
||||||
|
|
||||||
|
// css任务:压缩css
|
||||||
|
async function cssTask() {
|
||||||
|
const ctx = gulp.src(cssGlob, {
|
||||||
|
ignore: [staticGlob],
|
||||||
|
});
|
||||||
|
const condition = env === "prod";
|
||||||
|
return ctx
|
||||||
|
.pipe(gulpIf(condition, cleanCss())) // css样式压缩
|
||||||
|
.pipe(gulpIf(condition, writeFileToFileSystem(path.join(assetsDir))))
|
||||||
|
.pipe(gulpIf(!condition, writeFileToMemory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const css = cssTask;
|
||||||
|
|
||||||
|
// 静态文件目录,直接复制
|
||||||
|
async function staticFile() {
|
||||||
|
const condition = env === "prod";
|
||||||
|
const staticDir = "/static";
|
||||||
|
return gulp
|
||||||
|
.src(staticGlob)
|
||||||
|
.pipe(gulpIf(condition, writeFileToFileSystem(assetsDir)))
|
||||||
|
.pipe(gulpIf(!condition, writeFileToMemory(staticDir)));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const staticFileTask = staticFile;
|
||||||
|
|
||||||
|
// 其他文件:直接复制(除了html, css,js文件和static目录)
|
||||||
|
async function otherFile() {
|
||||||
|
const condition = env === "prod";
|
||||||
|
return gulp
|
||||||
|
.src(allFileGlob, {
|
||||||
|
ignore: [htmlGlob, cssGlob, jsGlob, staticGlob],
|
||||||
|
})
|
||||||
|
.pipe(gulpIf(condition, writeFileToFileSystem(assetsDir)))
|
||||||
|
.pipe(gulpIf(!condition, writeFileToMemory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const otherFileTask = otherFile;
|
||||||
|
|
||||||
|
// 打包任务:清除dist目录,然后并行执行html、js、css、其他文件、static等任务
|
||||||
|
export const build = gulp.series(setEnv("prod"), cleanTask, gulp.parallel(html, js, css, otherFileTask, staticFileTask));
|
||||||
|
// server任务:开启一个本地服务器
|
||||||
|
async function serverTask() {
|
||||||
|
browsersyncOptions = browsersyncOptions && typeof browsersyncOptions === "object" ? browsersyncOptions : {};
|
||||||
|
|
||||||
|
const httpProxyList = Object.keys(httpProxy).map((prefix) => createProxyMiddleware(prefix, httpProxy[prefix]));
|
||||||
|
return browserSync.init({
|
||||||
|
...browsersyncOptions,
|
||||||
|
middleware: [
|
||||||
|
...httpProxyList,
|
||||||
|
// 自定义中间件来从内存文件系统中提供文件
|
||||||
|
function (req, res, next) {
|
||||||
|
let fileLogicPath = req.url.split("?")[0];
|
||||||
|
let url = fileLogicPath === "/" ? "/index.html" : fileLogicPath;
|
||||||
|
let filePath = path.join(__dirname, "/", devAssetsDir, ...url.split("/"));
|
||||||
|
mfs.readFile(decodeURIComponent(filePath), (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
const map = {
|
||||||
|
ENOENT: () => console.error(`\x1b[31m找不到文件或目录:${err.path}\x1b[0m`),
|
||||||
|
};
|
||||||
|
map[err.code] ? map[err.code]() : console.error(err);
|
||||||
|
res.statusCode = 404;
|
||||||
|
res.end(`not found ${req.url}`);
|
||||||
|
} else {
|
||||||
|
res.end(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
],
|
||||||
|
server: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const server = serverTask;
|
||||||
|
|
||||||
|
// 监听文件的修改,执行对应的任务
|
||||||
|
async function watchTask() {
|
||||||
|
gulp.watch(htmlGlob, gulp.series(html)).on("change", browserSync.reload);
|
||||||
|
gulp.watch(jsGlob, gulp.series(js)).on("change", browserSync.reload);
|
||||||
|
gulp.watch(cssGlob, gulp.series(css)).on("change", browserSync.reload);
|
||||||
|
gulp.watch(staticGlob, gulp.series(staticFileTask)).on("change", browserSync.reload);
|
||||||
|
gulp.watch(allFileGlob, gulp.series(otherFileTask)).on("change", browserSync.reload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const watch = watchTask;
|
||||||
|
|
||||||
|
// 开发服务
|
||||||
|
export const dev = gulp.series(setEnv("dev"), gulp.parallel(html, js, css, staticFileTask, otherFileTask), (cb) => setTimeout(() => cb(), 3000), server, watch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析模块映射
|
||||||
|
* @param {Object} moduleMap
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function parseModuleMap(moduleMap) {
|
||||||
|
const newModuleMap = {};
|
||||||
|
Object.keys(moduleMap).forEach((fileId) => {
|
||||||
|
const newId = `#include(${fileId})`;
|
||||||
|
newModuleMap[newId] = moduleMap[fileId];
|
||||||
|
});
|
||||||
|
return newModuleMap;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 把文件流写入到内存中
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function writeFileToMemory() {
|
||||||
|
return map(function mapFile(file, cb) {
|
||||||
|
const filepath = path.resolve(file.path);
|
||||||
|
const dir = path.dirname(filepath);
|
||||||
|
if (!mfs.existsSync(dir)) {
|
||||||
|
mfs.mkdirpSync(dir);
|
||||||
|
}
|
||||||
|
file.contents && mfs.writeFileSync(filepath, file.contents);
|
||||||
|
cb(null, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 把文件流写入到硬盘中
|
||||||
|
* @param {String} assetsDir 写入到哪个目录,如根目录的dist,则assetsDir位'dist'
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function writeFileToFileSystem(assetsDir) {
|
||||||
|
return map(async function mapFile(file, cb) {
|
||||||
|
const relativePath = path.relative(path.join(process.cwd(), devAssetsDir), file.path);
|
||||||
|
const destFilePath = path.join(process.cwd(), assetsDir, relativePath);
|
||||||
|
const dirPath = path.dirname(destFilePath);
|
||||||
|
try {
|
||||||
|
if (file.contents) {
|
||||||
|
await fs.access(dirPath).catch(() => fs.mkdir(dirPath, { recursive: true }));
|
||||||
|
await fs.writeFile(destFilePath, file.contents);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
cb(null, file);
|
||||||
|
});
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "gulp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "gulp dev",
|
||||||
|
"build": "gulp build"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.24.0",
|
||||||
|
"@babel/preset-env": "^7.24.0",
|
||||||
|
"browser-sync": "^3.0.2",
|
||||||
|
"del": "^7.1.0",
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-babel": "^8.0.0",
|
||||||
|
"gulp-clean-css": "^4.3.0",
|
||||||
|
"gulp-debug": "^5.0.1",
|
||||||
|
"gulp-htmlmin": "^5.0.1",
|
||||||
|
"gulp-if": "^3.0.0",
|
||||||
|
"gulp-ignore": "^3.0.0",
|
||||||
|
"gulp-replace": "^1.1.4",
|
||||||
|
"gulp-sass": "^5.1.0",
|
||||||
|
"gulp-uglify": "^3.0.2",
|
||||||
|
"http-proxy-middleware": "^2.0.6",
|
||||||
|
"map-stream": "^0.0.7",
|
||||||
|
"memory-fs": "^0.5.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user