### 前言 在以前開發的環境中需要引用==前端==外部元件庫,常見的作法是前往元件庫的官方網站;例如 [Jquery](https://jquery.com/),[Bootstrap](https://getbootstrap.com/),然後找到 Download 的連結,將整包資源下載到開發環境中,然後透過以下方式進行引用。 ```html <script src="script/jquery/jquery.min.js"></script> ``` 但是可以發現到,近幾年這些元件庫提供另外一種安裝的方式,那就是==npm==。 例如:你可以在 Bootstrap 的首頁看到這個指令 ```shell npm i bootstrap@5.3.3 ``` 目前現有的前端框架,不僅在開發階段、部署階段,已經離不開 npm 了,甚至框架已經包含了所有需要的開發功能。 所以已經會使用前端框架開發的同學可以離開了。 這篇針對的是:還沒使用前端框架、還在使用 .NET MVC / RazorPage 等...後端框架開發的對象。 ### 前置作業 既然要使用==npm==,可以透過安裝 [Node.js](https://nodejs.org/en) 來取得。 安裝完成後可以在cmd 中透過以下指令確定是否安裝成功,以及目前安裝的版本。 ```shell C:\Users\> node -v C:\Users\> npm -v ``` 先在你的開發根目錄中執行 npm init 來產生 package.json 檔案 ```shell! D:\YourSite> npm init ``` 然後執行以下指令來安裝 Bootstrap 套件 ```shell! D:\YourSite> npm install bootstrap # install 可以簡寫成 i ``` 目前的 package.json 的內容應該是這樣 ```json { "name": "demosite", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "bootstrap": "^5.3.3" } } ``` 可以看到安裝的套件被放到 .\node_modules,然後只要將 node_modules 裡面的東西,全部 Copy 到開發的站台裡面就大功告成了...嗎? --- ### 當然不是這樣 首先必須在你的開發環境中安裝一個 全域 的 工具 gulp-cli ```shell npm install --global gulp-cli ``` 然後在你的專案中安裝以下套件 ```shell #gulp.js npm install gulp --save-dev #壓縮 css npm install gulp-clean-css --save-dev #合併文件 npm install gulp-concat --save-dev #壓縮 js npm install gulp-uglify --save-dev #重新命名 npm install gulp-rename --save-dev #刪除文件、文件夾 npm install rimraf --save-dev #監聽文件變化 npm install gulp-changed --save-dev ``` 目前的 package.json 的內容應該是這樣 ```json { "name": "demosite", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "bootstrap": "^5.3.3" }, "devDependencies": { "gulp": "^5.0.0", "gulp-changed": "^5.0.2", "gulp-clean-css": "^4.3.0", "gulp-concat": "^2.6.1", "gulp-rename": "^2.0.0", "gulp-uglify": "^3.0.2", "rimraf": "^5.0.7" } } ``` ### 配置 gulpfile.mjs 在專案根目錄底下建立一個 檔案名為 : gulpfile.mjs ```javascript= "use strict"; //載入 gulp 相關套件 import gulp from "gulp"; import { rimraf } from "rimraf"; import concat from "gulp-concat"; import cssmin from "gulp-clean-css"; import rename from "gulp-rename"; import uglify from "gulp-uglify"; import changed from "gulp-changed"; //定義 wwwroot 下的各文件存放路徑 const paths = { root: "./wwwroot/", css: './wwwroot/css/', js: './wwwroot/js/', lib: './wwwroot/lib/' }; //css paths.cssDist = paths.css + "**/*.css";// 匹配所有 css 的文件所在路徑 paths.minCssDist = paths.css + "**/*.min.css";//匹配所有 css 對應壓縮後的文件所在路徑 paths.concatCssDist = paths.css + "app.min.css";// 將所有的 css 壓縮到一個 css 文件後的路徑 //js paths.jsDist = paths.js + "**/*.js";// 匹配所有 js 的文件所在路徑 paths.minJsDist = paths.js + "**/*.min.js";// 匹配所有 js 對應壓縮後的文件所在路徑 paths.concatJsDist = paths.js + "app.min.js";// 將所有的 js 壓縮到一個 js 文件後的路徑 //使用 npm 下載的前端組件包 const libs = [ {name: "jquery", dist: "./node_modules/jquery/dist/**/*.*"}, {name: "bootstrap", dist: "./node_modules/bootstrap/dist/**/*.*"} ]; //清除 wwwroot 下的 min.css 和 min.js 文件 gulp.task("clean:css", done => rimraf(paths.minCssDist, done)); gulp.task("clean:js", done => rimraf(paths.minJsDist, done)); gulp.task("clean", gulp.series(["clean:js", "clean:css"])); //移動前端組件包到 wwwroot/lib 下 gulp.task("move", done => { libs.forEach(function (item) { gulp.src(item.dist) .pipe(gulp.dest(paths.lib + item.name + "/dist")); }); done() }); //將所有的 css 文件壓縮到對應的 min.css gulp.task("min:css", () => { return gulp.src([paths.cssDist, "!" + paths.minCssDist], {base: "."}) .pipe(rename({suffix: '.min'})) .pipe(changed('.')) .pipe(cssmin()) .pipe(gulp.dest('.')); }); //將所有的 css 文件合並打包壓縮到 app.min.css 中 gulp.task("concatmin:css", () => { return gulp.src([paths.cssDist, "!" + paths.minCssDist], {base: "."}) .pipe(concat(paths.concatCssDist)) .pipe(changed('.')) .pipe(cssmin()) .pipe(gulp.dest(".")); }); //將所有的 js 文件壓縮到對應的 min.js gulp.task("min:js", () => { return gulp.src([paths.jsDist, "!" + paths.minJsDist], {base: "."}) .pipe(rename({suffix: '.min'})) .pipe(changed('.')) .pipe(uglify()) .pipe(gulp.dest('.')); }); //將所有的 js 文件合並打包壓縮到 app.min.js 中 gulp.task("concatmin:js", () => { return gulp.src([paths.jsDist, "!" + paths.minJsDist], {base: "."}) .pipe(concat(paths.concatJsDist)) .pipe(changed('.')) .pipe(uglify()) .pipe(gulp.dest(".")); }); gulp.task("min", gulp.series(["min:js", "min:css"])); gulp.task("concatmin", gulp.series(["concatmin:js", "concatmin:css"])); //監控 css 和 js 文件的變化,自動執行相應的任務 gulp.task("auto", () => { gulp.watch(paths.css, gulp.series(["min:css", "concatmin:css"])); gulp.watch(paths.js, gulp.series(["min:js", "concatmin:js"])); }); ``` 上面的文件中定義了幾個任務 + move 將 libs 中的套件複製到 wwwroot/lib 下 + min 把 wwwroot/css 、 wwwroot/js 中的css和js,每一個都壓縮成xxx.min.css/xxx.min.js 可以透過以下指令查看定義了那些任務 ```shell gulp --tasks Tasks for D:\_DEMO\DemoSite\gulpfile.mjs ├── clean:css ├── clean:js ├─┬ clean │ └─┬ <series> │ ├── clean:js │ └── clean:css ├── move ├── min:css ├── concatmin:css ├── min:js ├── concatmin:js ├─┬ min │ └─┬ <series> │ ├── min:js │ └── min:css ├─┬ concatmin │ └─┬ <series> │ ├── concatmin:js │ └── concatmin:css └── auto ``` 然後就可以透過 gulp task-name 指令來執行任務 ```shell ## 將 libs 中的套件複製到 wwwroot/lib 下 gulp move ``` 若是之後有安裝新的套件,就要去修改 gulpfile.mjs 的內容 ```javascript= //使用 npm 下載的前端組件包 const libs = [ {name: "jquery", dist: "./node_modules/jquery/dist/**/*.*"}, {name: "bootstrap", dist: "./node_modules/bootstrap/dist/**/*.*"} ]; ``` 不要忘記執行 gulp move ,否則新安裝的套件不會複製到 lib 中。 ```shell ## 將 libs 中的套件複製到 wwwroot/lib 下 gulp move ``` ### 壓縮自己寫的 javascript 執行任務:壓縮 javascript ```shell ## 將 wwwroot/js 中的 js 檔案 壓縮成 min.js gulp min:js ``` 看一下 min:js 實際上做了哪些事情 ```javascript= gulp.task("min:js", () => { return gulp.src([paths.jsDist, "!" + paths.minJsDist], {base: "."}) /*重命名文件:使用 gulp-rename 插件給文件加上 .min 後綴。例如,app.js 會被重命名為 app.min.js。*/ .pipe(rename({suffix: '.min'})) /*檢查文件變更:使用 gulp-changed 插件只處理那些已經改變的文件,這樣可以提高效率,避免不必要的重新壓縮。*/ .pipe(changed('.')) /*壓縮 JavaScript 文件:使用 gulp-uglify 插件來壓縮和最小化 JavaScript 文件,這樣可以減小文件體積,提升載入速度。*/ .pipe(uglify()) .pipe(gulp.dest('.')); }); ``` --- 參考來源 [1.使用NPM和gulp管理前端靜態文件](https://www.cnblogs.com/deali/p/15905760.html)