Asp-Net-Core開發筆記:使用NPM和gulp管理前端靜態檔案

程式設計實驗室發表於2022-02-17

前言

本文介紹的是AspNetCore的MVC專案,WebApi+獨立前端這種前後端分離的專案就不需要多此一舉了~預設前端小夥伴是懂得使用前端工具鏈的。

為啥要用MVC這種服務端渲染技術呢?

  1. 簡單專案不需要強行分離增加複雜度(如:我正在開發的部落格專案)
  2. 後端渲染利於SEO,對部落格網站友好

OK,雖然MVC的技術老了點,但依然可以結合現代前端工具鏈來提高效率

本文的食用需要先安裝好Node.js環境,下載地址:https://nodejs.org/en/download

在開始前,先看看我們的專案檔案結構

  • Blog/
    • Blog.Web/
      • Program.cs
      • Blog.Web.csproj
    • Blog.Data/
    • Blog.sln

使用NPM安裝依賴

首先在專案根目錄(也就是Blog/Blog.Web)執行

npm init

生成package.json檔案

完成之後專案結構應該類似這樣

  • Blog/
    • Blog.Web/
      • Program.cs
      • Blog.Web.csproj
      • package.json (npm init 命令建立的檔案)

然後編輯package.json或者使用命令列npm install bootstrap來新增需要的前端庫

安裝的前端庫會儲存在Blog/Blog.Web/node_modules這個目錄下,但我們的靜態檔案需要放在Blog/Blog.Web/wwwroot裡才行,也就是說,我們需要將使用到的 npm 包移動到 wwwroot 檔案下。

怎麼搞?手動移動或複製是不可能的,太麻煩了。

這時候就要藉助自動化工具,這裡選擇了gulp.js,用於實現自動移動檔案,打包壓縮 js、css、image、刪除檔案等操作。提高生產力~

安裝gulp

首先安裝gulp全域性工具

npm install --global gulp-cli

然後在專案中安裝gulp以及幾個外掛作為開發依賴(devDependencies)

//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檔案應該類似下面這樣:

{
  "name": "star-blog",
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-changed": "^4.0.3",
    "gulp-clean-css": "^4.3.0",
    "gulp-concat": "^2.6.1",
    "gulp-rename": "^2.0.0",
    "gulp-uglify": "^3.0.2",
    "rimraf": "^3.0.2"
  },
  "dependencies": {
      ...
  }
}

配置gulp

繼續在根目錄(和package.json同級目錄)下新建gulpfile.js檔案

/// <binding BeforeBuild='min' Clean='clean' ProjectOpened='auto' />
"use strict";

//載入使用到的 gulp 外掛
const gulp = require("gulp"),
    rimraf = require("rimraf"),
    concat = require("gulp-concat"),
    cssmin = require("gulp-clean-css"),
    rename = require("gulp-rename"),
    uglify = require("gulp-uglify"),
    changed = require("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: "popper", dist: "./node_modules/popper.js/dist/**/*.*"},
    {name: "bootstrap", dist: "./node_modules/bootstrap/dist/**/*.*"},
    {name:"bootswatch",dist: "./node_modules/bootswatch/dist/**/*.*"}
];

//清除壓縮後的檔案
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"]));

//移動 npm 下載的前端元件包到 wwwroot 路徑下
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"]));


//監聽檔案變化後自動執行
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常量裡配置的node_modules包的dist資料夾移動到wwwroot/lib
  • min:把我們在wwwroot/csswwwroot/js裡寫的css和js,每一個都壓縮成xxx.min.css/xxx.min.js
  • concatmin:把上面min壓縮的所有css和js,合成一個app.min.cssapp.min.js
  • auto:自動監聽檔案變化後自動執行上面的minconcatmin任務

在終端中輸入gulp --tasks,可以檢視我們定義的這些任務

> gulp --tasks
[17:37:44] Tasks for /home/da/Code/StarBlog/StarBlog.Web/gulpfile.js
[17:37:44] ├── clean:css
[17:37:44] ├── clean:js
[17:37:44] ├─┬ clean
[17:37:44] │ └─┬ <series>
[17:37:44] │   ├── clean:js
[17:37:44] │   └── clean:css
[17:37:44] ├── move
[17:37:44] ├── min:css
[17:37:44] ├── concatmin:css
[17:37:44] ├── min:js
[17:37:44] ├── concatmin:js
[17:37:44] ├─┬ min
[17:37:44] │ └─┬ <series>
[17:37:44] │   ├── min:js
[17:37:44] │   └── min:css
[17:37:44] ├─┬ concatmin
[17:37:44] │ └─┬ <series>
[17:37:44] │   ├── concatmin:js
[17:37:44] │   └── concatmin:css
[17:37:44] └── auto

使用gulp task-name的命令可以執行任務,例如:

> gulp min
[17:41:41] Using gulpfile /home/da/Code/StarBlog/StarBlog.Web/gulpfile.js
[17:41:41] Starting 'min'...
[17:41:41] Starting 'min:js'...
[17:41:41] Finished 'min:js' after 19 ms
[17:41:41] Starting 'min:css'...
[17:41:41] Finished 'min:css' after 21 ms
[17:41:41] Finished 'min' after 44 ms

這就完成了把我們在wwwroot/csswwwroot/js裡寫的css和js,每一個都壓縮成xxx.min.css/xxx.min.js的任務。方便!

結合IDE

VS我沒有用過,我是用Rider做開發的,所以只介紹一下rider的

很簡單,開啟 Run/Debug Configuration,在新增配置裡面選擇 JavaScript Build Tools 裡的 Gulp.js

然後選擇專案裡的GulpFile,Tasks欄下拉可以看到我們定義好的任務,直接新增就完事了

新增完就像C#專案一樣,可以直接執行

razor裡使用

使用Gulp.js收集靜態檔案到wwwroot目錄後,razor檔案裡的引用需要小小的改一下,如下:

引用CSS檔案

<link rel="stylesheet" href="~/lib/fontawesome-free-6.0.0-web/css/all.css">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="~/lib/bootswatch/dist/united/bootstrap.min.css">
<link rel="stylesheet" href="~/css/app.min.css">

引用JS檔案

<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/app.min.js"></script>

大功告成!

參考資料

相關文章