初探gulp,體會前端工程化

前言

本文章用gulp搭建一個react開發的自動化工程,體會一下前端工程化帶來的樂趣css

準備

安裝gulp

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複製代碼

編譯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/"));
}複製代碼

編譯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/"));
}複製代碼

編譯html文件的目的是替換相應的東西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>複製代碼

編譯scss文件

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

相關文章
相關標籤/搜索