本文章用gulp搭建一個react開發的自動化工程,體會一下前端工程化帶來的樂趣css
準備npm install --global gulp-cli # 全局安裝複製代碼
cd your-project npm init -y or yarn init -y npm install --save-dev gulp # 項目依賴複製代碼
yarn add gulp-sass fibers autoprefixer gulp-postcss gulp-html-replace gulp-rename browserify babelify vinyl-buffer gulp-uglify gulp-ejs gulp-webserver node-sass複製代碼
-- src |-- ios-switch |-- index.html |-- index.jsx |-- index.scss -- gulpfile.js -- template |-- index.ejs |-- index1.ejs複製代碼
function jsxCompile(path, dirname) { let templatePath = []; templatePath.push(path); browserifyJs({entries: templatePath,debug: true,transform: [ babelify.configure({presets: ["@babel/preset-env", "@babel/preset-react"], }), ], }) .bundle() .pipe(stream("index.js")) .pipe(buffer()) .pipe(uglify()) .pipe( rename({dirname: dirname,basename: "index",extname: ".js", }) ) .pipe(gulp.dest("./dist/")); }複製代碼
function htmlCompile(path, dirname) { gulp .src(path) .pipe( htmlReplace({css: "./index.css",js: "./index.js", }) ) .pipe( rename({ dirname,basename: "index",extname: ".html", }) ) .pipe(gulp.dest("./dist/")); }複製代碼
編譯html文件的目的是替換相應的東西html
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title><%= name %></title><script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script><script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script><script> // 暴露全局對象 const React = window.React; const ReactDOM = window.ReactDOM; // 全局引用react 是每次打包jsx的時候都會從新打包,速度很慢,爲了節約打包時間,cdn引入</script><!-- build:css --><!-- endbuild --> </head> <body><div id="app"></div> </body> <!-- build:js --> <!-- endbuild --></html>複製代碼
function sassCompile(path, dirname) { gulp .src(path) .pipe( sass({ fiber: Fiber, outputStyle: "compressed" }).on("error", sass.logError ) ) .pipe(postcss([autoprefixer()])) .pipe( rename({ dirname,basename: "index",extname: ".css", }) ) .pipe(gulp.dest("./dist/")); }複製代碼
咱們應該監聽文件下文件的變化,來本身進行編譯前端
const watcher = watch( ["./src/**/*.scss", "./src/**/*.html", "./src/**/*.jsx"], {} ); watcher.on("change", function (pathL, stats) { console.log(`File, ${pathL} change`); let { pathName, dirname, extname } = getExtName(pathL); if (extname === ".html") {console.log("htmlCompile"); htmlCompile(pathL, dirname); } else if (extname === ".scss") {console.log("sassCompile"); sassCompile(pathL, dirname); } else if (extname === ".jsx") {console.log("jsxCompile"); jsxCompile(pathL, dirname); } });複製代碼
同時咱們應該在建立文件夾的時候自動生成文件夾下的內容,和生成路由文件node
watcher.on("add", function (router) { console.log(router, "add watcher"); let { extname } = getExtName(router); if (extname === ".html") {const { dir } = path.parse(router);const res = dir.split("\\"); htmlCompile(router, res[1]); buildRouter(); } });const RouterWatch = watch("./src/*"); RouterWatch.on("addDir", function (router) { console.log(`${router} change`); const { name } = path.parse(router); gulp .src("./template/index1.ejs") .pipe( ejs({ name, }) ) .pipe( rename({basename: "index",extname: ".html", }) ) .pipe(gulp.dest(router)); });// 生成路由function buildRouter() { let routers = fs.readdirSync("./src"); routers = routers.map((router) => {let template = path.join("./src", router);let stat = fs.lstatSync(template);if (stat.isDirectory()) { return {link: "./" + router,fileName: "index.html",linkName: router, }; } }); routers = routers.filter((v) => v !== undefined); return gulp .src("./template/index.ejs") .pipe( ejs({routes: routers, }) ) .pipe( rename({extname: ".html", }) ) .pipe(gulp.dest("./dist")); }複製代碼
function server() { build(); // 考慮到 build的構建沒有超過 100ms 延時1000ms 確保 build()構建完畢(可能會出錯,可是沒有想到更好地辦法) setTimeout(() => {return gulp.src("./dist").pipe( webserver({port: 8001,open: true,fallback: "index.html",allowEmpty: true,livereload: { enable: true, filter: function (fileName) {if (fileName === "index.html") { return true; } else { return false; } }, }, }) ); }, 1000); }function build() { buildRouter(); htmlCompile("./src/ios-switch/index.html", "ios-switch"); sassCompile("./src/ios-switch/index.scss", "ios-switch"); jsxCompile("./src/ios-switch/index.jsx", "ios-switch"); }複製代碼
const gulp = require("gulp");const { watch } = gulp;const sass = require("gulp-sass");const Fiber = require("fibers");const autoprefixer = require("autoprefixer");const postcss = require("gulp-postcss");const htmlReplace = require("gulp-html-replace");const rename = require("gulp-rename");const path = require("path");const browserifyJs = require("browserify");const babelify = require("babelify");const stream = require("vinyl-source-stream");const buffer = require("vinyl-buffer");const uglify = require("gulp-uglify");const ejs = require("gulp-ejs");const fs = require("fs");const webserver = require("gulp-webserver"); sass.compiler = require("node-sass");// sass 編譯function sassCompile(path, dirname) { gulp .src(path) .pipe( sass({ fiber: Fiber, outputStyle: "compressed" }).on("error", sass.logError ) ) .pipe(postcss([autoprefixer()])) .pipe( rename({ dirname,basename: "index",extname: ".css", }) ) .pipe(gulp.dest("./dist/")); }// html編譯function htmlCompile(path, dirname) { gulp .src(path) .pipe( htmlReplace({css: "./index.css",js: "./index.js", }) ) .pipe( rename({ dirname,basename: "index",extname: ".html", }) ) .pipe(gulp.dest("./dist/")); }// jsx編譯function jsxCompile(path, dirname) { let templatePath = []; templatePath.push(path); browserifyJs({entries: templatePath,debug: true,transform: [ babelify.configure({presets: ["@babel/preset-env", "@babel/preset-react"], }), ], }) .bundle() .pipe(stream("index.js")) .pipe(buffer()) .pipe(uglify()) .pipe( rename({dirname: dirname,basename: "index",extname: ".js", }) ) .pipe(gulp.dest("./dist/")); }const watcher = watch( ["./src/**/*.scss", "./src/**/*.html", "./src/**/*.jsx"], {} ); watcher.on("change", function (pathL, stats) { console.log(`File, ${pathL} change`); let { pathName, dirname, extname } = getExtName(pathL); if (extname === ".html") {console.log("htmlCompile"); htmlCompile(pathL, dirname); } else if (extname === ".scss") {console.log("sassCompile"); sassCompile(pathL, dirname); } else if (extname === ".jsx") {console.log("jsxCompile"); jsxCompile(pathL, dirname); } }); watcher.on("add", function (router) { console.log(router, "add watcher"); let { extname } = getExtName(router); if (extname === ".html") {const { dir } = path.parse(router);const res = dir.split("\\"); htmlCompile(router, res[1]); buildRouter(); } });const RouterWatch = watch("./src/*"); RouterWatch.on("addDir", function (router) { console.log(`${router} change`); const { name } = path.parse(router); gulp .src("./template/index1.ejs") .pipe( ejs({ name, }) ) .pipe( rename({basename: "index",extname: ".html", }) ) .pipe(gulp.dest(router)); });// 生成路由function buildRouter() { let routers = fs.readdirSync("./src"); routers = routers.map((router) => {let template = path.join("./src", router);let stat = fs.lstatSync(template);if (stat.isDirectory()) { return {link: "./" + router,fileName: "index.html",linkName: router, }; } }); routers = routers.filter((v) => v !== undefined); return gulp .src("./template/index.ejs") .pipe( ejs({routes: routers, }) ) .pipe( rename({extname: ".html", }) ) .pipe(gulp.dest("./dist")); }function server() { build(); // 考慮到 build的構建沒有超過 100ms 延時1000ms 確保 build()構建完畢(可能會出錯,可是沒有想到更好地辦法) setTimeout(() => {return gulp.src("./dist").pipe( webserver({port: 8001,open: true,fallback: "index.html",allowEmpty: true,livereload: { enable: true, filter: function (fileName) {if (fileName === "index.html") { return true; } else { return false; } }, }, }) ); }, 1000); }function build() { buildRouter(); htmlCompile("./src/ios-switch/index.html", "ios-switch"); sassCompile("./src/ios-switch/index.scss", "ios-switch"); jsxCompile("./src/ios-switch/index.jsx", "ios-switch"); }function getExtName(router) { let pathName = path.parse(router); let dirname = pathName.dir.replace("src\\", ""); let extname = pathName.ext; return { pathName, dirname, extname, }; }// exports.build = build;exports.default = server;複製代碼
項目還有不少BUG,好比gulp對刪除文件夾會直接報錯,沒法進行全局異常捕獲,但願有大佬能夠幫我解決一下react