---
# System prepended metadata

title: 在非前端框架中引用npm套件

---

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