### 前言
在以前開發的環境中需要引用==前端==外部元件庫,常見的作法是前往元件庫的官方網站;例如 [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)