前端筆記之NodeJS(二)路由&REPL&模塊系統&npm


一、路由機制(靜態資源文件處理)

1.1 Nodejs沒有根目錄

MIME類型:http://www.w3school.com.cn/media/media_mimeref.asp

Apache中,它會自動將htdocs文件夾提供靜態化路由服務。

但是Nodejs沒有這個機制。

 

在文件夾中創建這樣的層次目錄:

┠ www

┋┠ a

┋┋┠ b

┋┋┋┠ page.html

┠ 11-Nodejs沒有根目錄容器.js

 

訪問的時候,可以看見page.html頁面: 

var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req,res){
    res.setHeader("Content-Type", "text/html;charset=UTF8");

    fs.readFile("./www/page.html" , (err,data)=>{ res.end(data.toString()); })
});

server.listen(3000);

會發現URL中看不出來物理文件的真實位置。

 

可以用req.url來識別url地址,從而呈遞不同的文件:

page.html頁面:

 

<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style type="text/css">
        div{
            width: 300px;
            height: 100px;
            background: orange;
        }
    </style>
    <link rel="stylesheet" href="aaa">
</head>
<body>
    <h1>page頁面!</h1>
    <div></div>
      <img src="images/d1.jpg">
    <img src="images/d2.jpg">
      <img src="images/d3.jpg">
</body>
</html>

 

var server = http.createServer(function(req,res){
    console.log(req.url)
    if(req.url == "/"){
        fs.readFile("./www/page.html",(err,data)=>{
            res.setHeader("Content-type","text/html;charset=UTF8");
            res.end(data.toString());
        });
 }else if(req.url == "/images/d1.jpg"){
        fs.readFile("./www/images/baby1.jpg",(err,data)=>{
            res.setHeader("Content-type","image/jpeg");
            res.end(data);
        });
   }else if(req.url == "/images/d2.jpg"){
        fs.readFile("./www/images/d2.jpg",(err,data)=>{
            res.end(data);
        });
   }else if(req.url == "/d3.jpg"){
        fs.readFile("./www/images/d3.jpg",(err,data)=>{
            res.end(data);
        });
    }else if(req.url == "aaa"){
        fs.readFile("./www/css/css.css",(err,data)=>{
            res.setHeader("Content-type","text/css");
            res.end(data);
        });
    }else{
        res.setHeader("Content-type","text/html;charset=UTF8");
        res.end("404,沒有這個頁面!");
    }
});

紅色部分是發出的url請求,藍色部分是根據請求的url從而呈遞真實的文件,URL和真實的物理文件的路徑沒有任何關系!

比如www/a/b/c/d1.jpg可以被路由顯示為/d1.jpg


1.2頂級路由設計

Nodejs開啟了RestFul路由設計風格。簡單來說是:

可以通過這樣的路徑來查看100001號用戶的信息:
http://127.0.0.1:3000/student/100001

而不是老土的: http://127.0.0.1:3000/showinfo.php?id=100001

 

后面將知道可以利用POSTGET請求的不同,也可以讓一個URL有不同的操作。

這樣的路由的好處就是:不需要開辟過多的文件夾、並且不暴露技術細節

 

可以用字符串match方法,結合正則獲取路由中的某部分:


1.3 url模塊和path模塊

一個完整的URL,包括querystring部分(就是get請求字符串部分)、hash部分。

http://127.0.0.1:3000/a/b.html?id=123&name=xiaoming#aaa

此時的req.url是:

 

也就是說,querystring部分屬於req.url,但是hash不屬於。

但是我們要得到文件名部分,不想要querystring部分,如果正則匹配,太麻煩。

此時node中提供內置模塊:urlpathquerystring,他們都可以用於URL的識別。

 

var http = require("http");
var fs = require("fs");
var url = require("url");

var server = http.createServer(function(req,res){
    console.log(url.parse(req.url))
});
網址:http://127.0.0.1:3000/haha/1.html?id=123&name=xiaoming&sex=男#abc

輸出的內容:

 

沒有正確識別protocol協議、host主機名、port端口號等等,因為是Windows環境,有這個問題。

 

如果加上true,此時query部分將自動變為對象,方便我們操作

url.parse(req.url,true);

 

還有兩個模塊pathquerystring它們都是服務於url

var http = require('http');
var fs = require('fs');
var url = require('url');
var path = require('path');

var server = http.createServer(function(req,res){
    //將url字符串轉為json對象
    var urljson = url.parse(req.url,true);
    //得到文件路徑
    var pathname = urljson.pathname;

    //得到文件擴展名
    var extname = path.extname(pathname);

    console.log(extname)
});

server.listen(3000);

1.4自動路由

創建一個www根目錄文件夾,我們的程序能夠自動為里面的文件、圖片、cssjs加上路由,實現一個Apache

思想:用戶輸入什么URL,就用fs去讀那個文件

訪問/a.png ,就自動讀取www/a/b/c/a.png

url可能很復雜,比如:
http://127.0.0.1:3000/a/b/c.html?id=123&asf=32434#3243
要讀取c.html。就要過濾掉藍色的部分,當中有協議、域名、端口號、get請求查詢字符串、hash。
使用內置url模塊:
var pathname = url.parse(req.url).pathname;
url.parse(req.url) 可以將這個url拆分,比如.pathname表示上面紅色的部分。

有幾個不好用的地方,首先就是content-type的事,

 

如果我們訪問的是.html文件,content-type就應該是text/html。如果訪問一個.jpg,此時應該是image/jpeg。請參考:http://www.w3school.com.cn/media/media_mimeref.asp

然后就是不能自動識別index文件。比如我們輸入:
http://127.0.0.1:3000/a
應該讀取www中的a文件夾中的index.html

解決辦法:這種路徑都沒有拓展名,如果用戶輸入了一個URL不存在拓展名,則自動補充/index.html即可。

var http = require("http");
var fs = require("fs");
var url = require("url");
var path = require("path");

//准備mime類型的json
var mimejson = {
    ".jpg" : "image/jpeg",
    ".png" : "image/png",
    ".gif" : "image/gif",
    ".html": "text/html;charset=UTF8",
    ".css" : "text/css",
    ".js" : "application/x-javascript",
    ".ogg" : "audio/ogg",
    ".mp3" : "audio/mpeg"
}

var server = http.createServer(function(req,res){
    //訪問路徑
    var pathname = url.parse(req.url).pathname;
    //得到擴展名
    var extname = path.extname(pathname)

    //如果當前路徑不以擴展名結尾,此時表示這是一個文件夾形式的路徑,要自動補全index.html
    if(!extname){
        //如果不是以“/”結尾,此時會早瀏覽器識別圖片路徑層次有問題
        //比如http://127.0.0.1:3000/a和http://127.0.0.1:3000/a/不一樣
        //前者認為是同級目錄下的,后者認為是a文件夾中的
        if(pathname.substr(-1) != "/"){
            res.writeHead(302, {"Location": pathname + "/"})
        }

        pathname = pathname + "index.html";
        extname = "./html";
    }

    //檢查是否屬於已知的mime類型
    if(mimejson.hasOwnProperty(extname)){
        //設置MIME類型(下行報文頭)
        res.setHeader("Content-type", mimejson[extname]);
    }

    //讀取對應的真實文件路徑,這里將當前文件的路徑和www文件夾和訪問的路徑合並
    fs.readFile("./www/" + pathname , function(err,data){
        if(err){
            res.end("沒有這個文件");
            return;
        }
        res.end(data);
    })
});

server.listen(3000,function(err){
    console.log("服務器開啟成功,在3000端口,快打開瀏覽器看看吧!");
})
解決方案

二、總結REPL環境

2.1復習

NodeJS是什么?
  JavaScript RunTime(JavaScript運行環境),是將Chrome V8引擎移植到了服務器上追求自治性能的技術,可以搭建http服務器。
  使用的語言還是JavaScript,將js的觸角伸到了服務器端。
NodeJS有什么特點?
  Single Thread(單線程)
  Non-Blocking I/O(異步I/O,非阻塞I/O)
  Event-Driven(事件驅動)
NodeJS適合開發什么樣的業務?
  適合I/O頻繁的業務:留言本、貼吧、微博等等。
  不適合計算多的業務:語音識別、圖像識別等等。
NodeJS如何安裝?
    在windows下安裝了node,此時你的環境變量中就有了node文件夾的路    徑,此時用CMD命令就可以運行nodejs程序了。
如何執行NodeJS程序?
  ① 用CMD的cd命令進入項目文件夾
  ② 執行誰就node誰
內置模塊
  Nodejs中為了方便開發和最終的編譯的輕量,所以使用了“模塊”(modules)的概念。
  模塊指的是功能相關的js文件的集合,就稱為一個模塊。一個module指的是一個文件組,或者說一組文件。
  這一組文件可以小到只有一個文件,也就是說這一個module就只有一個js文件;也可以大到很多文件,甚至這一個module中還有其他module。

 

模塊用require()進行引用,我們學習的內置模塊有:

fs模塊用來處理文件
var fs = require("fs");
fs.readFile("./test.txt",(err,data)=>{

});
http模塊,創建服務器:
var http = require("http");
http.createServer((req,res)=>{
  req.url //用戶訪問的路徑
  res.write();
  res.end();
}).listen(3000,function(err){})
path模塊,主要負責和文件路徑有關系的事情:
var path = require("path");
path.extname(); //獲得文件拓展名
path.resolve(); //智能合並
url模塊,主要負責url地址的拆分等一些功能:
var url= require("url");
url.parse();

 

Nodejs中的路由:

Nodejs和apache不一樣,apache有自動的路由,但是nodejs沒有自動路由。
必須用req.url來識別訪問的路徑,然后用fs.readFile()去讀取某一個文件,然后res.end()出去。
Nodejs非常方便進行頂級路由設計,比如twitter的路由:
http://www.twitter.com/telangpu/followers
此時並沒有一個叫做telangpu的文件夾,也沒有followers的子文件夾!

 

什么是路由?

路由可以理解成根據請求不同的URL,映射到不同處理程序上。反過來,需要對每個不同的頁面定義不同的路由來實現區分界面。

簡單來說,路由就是給指定的頁面分配一個url地址。通過這個url地址,就能訪問到該頁面了。

比如寫了一個頁面:/static/public/game/index.html

服務器域名地址是:www.iqianduan.cn 通過一些方式,給該頁面配置了一個路由地址/game

那么,就可以通過http://www.iqianduan.cn/game訪問到上面這個index.html文件了

支持RESTful的路由,遵循國際規范。


2.2 REPL環境

介紹NodejsREPL環境。

Node.js REPL(Read Eval Print Loop:交互式解釋器) 表示一個電腦的環境,類似 Window 系統的終端或 Unix/Linux shell,我們可以在終端中輸入命令,並接收系統的響應。

讀取 - 讀取用戶輸入,解析輸入了Javascript 數據結構並存儲在內存中。

執行 - 執行輸入的數據結構

打印 - 輸出結果

循環 - 循環操作以上步驟直到用戶兩次按下 ctrl+c 按鈕退出Node REPL

 

這里和ChromeF12功能一樣,可以直接輸入語句,然后執行。

 

 

在REPL環境下,測試一下url.parse()語句:

 

 

url.parse()功能就是拆分url地址。

path.extname(url.parse("http://www.aaa.com/a/b/c.php?id=1&name=小明#12").pathname);


 

三、Nodejs的模塊系統

3.1先復習HTML環境下的js文件的關系

知識點1:在HTML中,script引用了誰,就會執行誰,瀏覽器一定能夠保證加載、運行順序的

<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script type="text/javascript" src="a.js"></script>
    <script type="text/javascript" src="b.js"></script>
    <script type="text/javascript" src="c.js"></script>
</body>
</html>

 

 知識點2:js文件不能“關住”變量作用域

a.js文件:
var zhongguoyidong = 10086;  //相當於給window添加了屬性
 b.js文件:
alert(zhongguoyidong);       //相當於訪問window的屬性

此時能夠彈出10086,也就是說a.js文件中定義的變量,b.js文件中能夠看見!

全局變量是window對象的屬性。

 

 知識點3IIFE關閉某個js文件時,這個js文件想向外“暴露”某些對象

(function(){
    var pi = 3.14;

    window.mianji = function(r){
        return pi * r * r;
    }
    window.zhouchang = function(r){
        return 2 * pi * r;
    }
})();

主頁面:

<script type="text/javascript" src="a.js"></script>
<script type="text/javascript">
     alert(mianji(10))
     alert(zhouchang(10))
</script>

 

看一種復雜的情況,a.js文件和b.js文件都向外暴露了相同的函數:

a.js

(function(){
    var pi = 3.14;

    window.mianji = function(r){
        return pi * r * r;
    }
    window.zhouchang = function(r){
        return 2 * pi * r;
    }
})();

b.js

(function(){
    var pi = 3.14;

    window.mianji = function(d,g){
        return 0.5 * d * g;
    }
})();

index.html

<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript">
     alert(mianji(10,2))
     alert(zhouchang(10))
</script>

b里面的mianji函數,將a里面的mianji函數覆蓋了。


3.2 Nodejs中的模塊概念

┣ modules
│┣ a.js
┣01.js

nodejs通過require()函數引用自己寫js文件,require誰,就立即運行誰。

a.js
console.log("我是a.js文件");


01.js require("./modules/a.js");

新增一個b.js文件

┣ modules
│┣ a.js
│┣ b.js
┣01.js
require("./modules/a.js"); //定義了一個變量
require("./modules/b.js"); //輸出這個變量
a.js
var aaa = 100;

b.js console.log(aaa);

運行01.js報錯。

 

Nodejsjs文件是天生隔離作用域的,因為沒有全局window對象的概念了。

 

即使將在01.js主文件中,也不能使用這個aaa變量
require("./modules/a.js");  //天生有閉包
console.log(aaa)    //報錯

3.3變量的暴露(exports.** = **

如果js文件中想要暴露什么,使用exports對象:

┣ modules
│┣ a.js
┣01.js
a.js
var zhongguoliantong = 10000; exports.zhongguoliantong = zhongguoliantong; //向外暴露變量
01.js
var a = require("./modules/a.js"); //接收暴露的對象 console.log(a.zhongguoliantong);

 

注意兩點(約定俗成):
向外暴露的時候,變量本身叫什么名,暴露的名字就叫什么。
exports.zhongguoliantong = zhongguoliantong; 

require接收時,模塊文件名(js文件名)是什么,接收的變量就叫什么名字
var a = require("./modules/a.js"); 

Nodejs的這種require + exports的模式叫CMD規范(Commond Module Definition),但不是nodejs發明的,

后面會介紹CMDAMD規范(Common.jsSea.jsrequire.js

 

現在有兩個模塊,都向外暴露mianji函數

┣ modules
│┣ yuan.js
│┣ sanjiaoxing.js
┣02.js
yuan.js
function mianji(r){ return 3.14 * r * r; } exports.mianji = mianji;
sanjiaoxing.js
function mianji(i,h){ return 0.5 * i * h; } exports.mianji = mianji;
02.js
var yuan = require("./modules/yuan.js"); var sanjiaoxing = require("./modules/sanjiaoxing.js"); console.log(yuan.mianji(10)); console.log(sanjiaoxing.mianji(10,3));

如果一個js文件有多個對象要暴露(就是這個模塊的API),此時寫多個exports.** = **即可。

function mianji(r){
    return 3.14 * r * r;
}
function zhouchang(r){
    return 2 * 3.14 * r;
}

exports.mianji = mianji;
exports.zhouchang = zhouchang;

3.4默認暴露(module.exports = **

┣ modules
│┣ People.js
┣03.js
People.js中,普通暴露的寫法

function People(name){ this.name = name; } People.prototype.changge = function(){ console.log(this.name + "在唱歌!"); } exports.People = People;
03.js
var People = require("./modules/People.js"); var xiaoming = new People.People("小明"); xiaoming.changge();

此時new的時候People.People這種寫法不優雅,因為模塊用普通暴露,普通暴露接收的People將自動成為exportsJSON對象,People.People()才是函數。

 

怎么辦?換一種暴露方法即可:

function People(name){
    this.name = name;
}
People.prototype.changge = function(){
    console.log(this.name + "在唱歌!");
}

module.exports = People;

var People = require("./modules/People.js");

var xiaoming = new People("小明");
xiaoming.changge();

這條語句和exports.** = **不同,module.exports = **寫法,接收的變量就成為你暴露的這個函數。

 

注意:一個文件夾不允許出現module.exports多次,只能出現一次。

總結:

 一個js文件如果有多個暴露(通過是多個API),使用exports.** = **的寫法

 一個js文件如果只要暴露一個對象,通常是類(構造函數),使用module.exports = **寫法


3.5注意事項

l 模塊如果要引用另一個模塊,使用相對路徑,相對自己出發,找到別人:

require的模塊中如果有異步語句,還是遵循昨天的“服務員”工作模式:

┣ modules
┃ ┣ loop1.js
┃ ┣ loop1.js
┣ 04.js
04.js
var loop1 = require("./modules/loop1.js");
loop1.js

require(
"./loop2.js"); console.log("我是loop1文件");
loop2.js有異步語句:

var fs = require("fs"); console.log("我是loop2文件") fs.readFile("./modules/test.txt",function(err,data){ console.log(data.toString()) })

原則上require按順序執行,但如果模塊有異步語句,此時不會傻等模塊執行完畢。


四、神奇的node_modules文件夾和模塊概念

node_modules是一個特殊的文件夾,只要放在這個文件夾中的js文件,在被require的時候,不需要詳細寫清楚路徑,nodejs可以自動向上查找找到它,node_modules還可以出現在項目目錄的任意父路徑層級上。但不會向下查找,只向上查找。

┣ node_modules
┃ ┣ yuan.js
┣ 05.js

 

05.js引用yuan.js的時候,沒有詳細些它的路徑,也能引用成功:

var yuan = require("yuan.js");  //而不是require("./node_modules")
console.log(yuan.mianji(10));

 

node_modules文件夾放到day02文件夾外面,就是上一層路徑中,還可以運行:

┣ node_modules
┃ ┣ yuan.js
┣ day02
┣┣  05.js

 

也就是說C:\node_study\day02\05.js文件可以依法引用以下:

C:\node_study\day02\node_modules\yuan.js
C:\node_study\node_modules\yuan.js
C:\node_modules\yuan.js

 

進一步的深入:

┣ node_modules
┃ ┣ yuan.js
┃ ┣ sanjiaoxing
┃ ┃ ┣ index.js
┣┣  05.js
var yuan = require("yuan.js");
var sanjiaoxing = require("sanjiaoxing");
console.log(yuan.mianji(10))
console.log(sanjiaoxing.mianji(10,2))

如果require的路徑沒有寫擴展名,表示引用的是node_modules文件夾中的sanjiaoxing文件夾中的index.js文件。

 

小題目,下面require實際上require 了誰?

比如項目目錄是:C:\nodejs_study\day02\

require("./a.js");             C:\nodejs_study\day02\a.js
require("./haha/a.js");      C:\nodejs_study\day02\haha\a.js
require("./haha");             C:\nodejs_study\day02\haha\index.js
require("a");                 C:\nodejs_study\day02\node_modules\a\index.js
require("a.js");             C:\nodejs_study\day02\node_modules\a.js

 

shuxue文件夾,去統領所有的模塊:

┣ node_modules
┃ ┃ shuxue
┃ ┃ ┣ yuan.js
┃ ┃ ┣ sanjiaoxing.js
┃ ┃ ┣ index.js
┣┣  06.js

 

 數學這個文件夾對外表示一種功能,就是數學的計算函數,此時shuxue就是一個模塊。

模塊是一根抽象的文件夾的關系概念,而不是物理的文件位置概念:

node_modules/shuxue/index.js

var yuan = require("./yuan.js");
var sanjiaoxing = require("./sanjiaoxing.js");

exports.yuan = yuan;
exports.sanjiaoxing = sanjiaoxing;
06.js主文件使用模塊
var shuxue = require("shuxue"); console.log(shuxue.yuan.mianji(10)) console.log(shuxue.yuan.zhouchang(10)) console.log(shuxue.sanjiaoxing.mianji(10,2))

五、npm包管理工具

隨着 web 應用越來越復雜,項目的結構和代碼量也變的愈加龐大,前端人員越來越需要在工程化的層面提高開發效率,前端開發是一個飛速發展的領域,市面上現在有各種各樣的工具來輔助我們開發,比如說我們在開發過程中就可能會用到下面這些工具:npmwebpackbabel等。

5.1 npm install命令

社區官網:https://www.npmjs.com/

中文文檔:https://www.npmjs.com.cn/

中文文檔:http://www.runoob.com/nodejs/nodejs-npm.html

     稱:node package managementnode包管理器)。

大家在這里共享自己編寫的模塊。

 

NPM 使用介紹

NPM是隨同NodeJS一起安裝的包管理工具,能解決NodeJS代碼部署上的很多問題,常見使用場景有以下幾種:

允許用戶從NPM服務器下載別人編寫的第三方包到本地使用。

允許用戶從NPM服務器下載並安裝別人編寫的命令行程序到本地使用。

允許用戶將自己編寫的包或命令行程序上傳到NPM服務器供別人使用。

由於新版的Nodejs已經集成了npm,所以之前npm也一並安裝好了。

可以通過CMD輸入"npm -v" 測試是否成功安裝。命令如下,出現版本提示表示安裝成功:

$ npm -v

 

比如現在有一個項目,要將數字換成大寫人民幣寫法,12345換成“一萬兩千三百四十五元整”。

我們去npm社區搜索“大寫金額”:

 

我們覺得nzh這個模塊號,決定用它。

下載方式是使用CMD命令,輸入:

npm install nzh //install表示安裝,nzh就是這個包(模塊)的名字

 語法:npm install 包名字  

 

 01.js 當然API都是從這https://www.npmjs.com/package/nzh抄的:

var Nzh = require("nzh");
var nzhcn = Nzh.cn;                 // 使用簡體中文,  另外有 Nzh.hk -- 繁體中文

console.log(nzhcn.encodeS(123456));              // 轉中文小寫 >> 十萬零一百一十一
console.log(nzhcn.encodeB(123456));              // 轉中文大寫 >> 壹拾萬零壹佰壹拾壹
console.log(nzhcn.encodeS("1.23456789e+21"));  // 科學記數法字符串 >> 十二萬三千四百五十六萬萬七千八百九十萬億
console.log(nzhcn.toMoney("100111.11")); // 轉中文金額 >> 人民幣壹拾萬零壹佰壹拾壹元壹角壹分

上面的代碼誰背誰傻。

 

新的需求又來了,老板說,我們要知道農歷,比如要查找201888日的農歷是多少?

於是又去npm社區搜索相關模塊:

 

決定使用solarlunar ,此時npm下載:

npm install solarlunar

 

API文件,直接抄代碼:

var solarLunar = require("solarLunar");

var solar2lunarData = solarLunar.solar2lunar(2018, 8, 8); // 陽歷轉為農歷
var lunar2solarData = solarLunar.lunar2solar(2018, 8, 8); // 農歷轉為陽歷
console.log(solar2lunarData)
console.log(lunar2solarData)

 

需求:用JS程序批量改圖片尺寸

var fs = require('fs');
var gm = require('gm').subClass({imageMagick: true});

//讀取文件目錄
fs.readdir("./images/", function(err,files){
    //批量循環遍歷-修改尺寸
    for(var i = 0;i < files.length;i++){
        gm('./images/' + files[i]).resize(50,50).write('./img/'+ files[i], function(err){
            if(err){
                console.log("失敗");
            }
        });
    }
})

之后,發現現在JS程序可以批量更改圖片尺寸了!

 

又來需求了,老板讓我把這個月的銷售額(已經在程序的數組中),生在Excel文件中:

https://www.npmjs.com/package/node-xlsx

npm install node-xlsx

 

下載完畢node-xlsx后,參考API寫代碼:

var xlsx = require("node-xlsx");
var fs = require("fs");

//數據
var data = [["月份","銷售額(萬)"],[1,90], [2,30], [3,190], [4,500]];
//生成Excel格式的數據
var buffer = xlsx.build([{name: "銷售表", data: data}]);
//生成Excel文件,並且將數據寫入
fs.writeFile("./銷售表.xlsx", buffer, function(err){
    if(err){
        console.log("生成失敗");
        return;
    }
    console.log("生成成功")
})

所以npm真的是好東西

l 資源很多

l 下載方便

l 依賴管理方便


5.2包依賴管理

package.jsonnpm安裝模塊時的依據。

每個項目的根目錄下面,一般都有一個package.json文件,定義了這個項目所需要的各種模塊,以及項目的配置信息(比如名稱、版本、許可證等數據)。npm install命令根據這個配置文件,自動下載所需的模塊,也就是配置項目所需的運行和開發環境。

使用場景:我需要AA依賴BB依賴C

常見的包管理工具都有循環依賴的功能,你只需要記住你要什么東西

 

package.json文件可以手工編寫,也可以使用npm init命令自動生成

創建一個身份證記錄自己的項目依賴了哪些npm包。

所以刪除node_modules文件夾,重新下載一次,這次要加上--save保存到身份證中。

npm init

這個命令可以創建package.json文件。

 

 

此時生成了一個package.json文件,這是項目的身份證:

{
  "name": "02-npm_study",   //項目名稱
  "version": "1.0.0",       //版本號
  "description": "這是我們的學習npm案例",    //描述
  "main": "app.js",         //入口文件
  "scripts": { //調試命令
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "牛逼"  //關鍵詞
  ],
  "author": "rope",   //作者
  "license": "ISC"      //版權協議
}

 

然后按照依賴,此時還是用npm install命令,但是要加上--save參數,表示記錄到package.json

npm install nzh --save

npm install --save nzh

 

此時node_modules文件夾還是會下載這些模塊,並且package.json文件中多出了dependencies依賴項:

{
  "name": "02-npm_study",
  "version": "1.0.0",
  "description": "這是我們的學習npm案例",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "牛逼"
  ],
  "author": "rope",
  "license": "ISC",
  "dependencies": {
    "gm": "^1.23.1",
    "node-xlsx": "^0.12.1",
    "nzh": "^1.0.3",
    "solarlunar": "^2.0.3" }
}

 

項目身份證的意義在於,記錄你的項目依賴了什么模塊,可以使用以下命令一次性下載回來:

npm install 

不指定任何包的名字,此時將會拉取所有package.json中聲明的dependencies依賴項

如何區分開發依賴和運行依賴(生產依賴)

當你的項目放到瀏覽器去運行的時候你還需要這個依賴嗎?如果需要那它就是生產(運行)依賴,反之是開發依賴。


 

5.3版本符號的意思

package.json文件的詳細介紹:https://docs.npmjs.com/files/package.json


5.4淘寶鏡像

npm在中國大陸沒有鏡像,下載速度慢,淘寶為我們搭建了民間鏡像。

http://npm.taobao.org/

 

安裝淘寶鏡像特別簡單,直接使用:

npm install -g cnpm --registry=https://registry.npm.taobao.org

-g表示在全局位置安裝

這條語句表示:在電腦安裝了一個叫cnpm的命令行工具,並且附加參數--registry為一個地址。

 

-g到底安裝在哪?用下面命令查看具體安裝位置:

npm root -g

這里相當於系統的一個底層位置,這可以安裝系統的CLI,也就是說-g安裝的不是項目依賴,也不是模塊。而是系統的CLI,就是給CMD豐富了一些功能,比如豐富了cnpm命令。

 

不需要知道那么多,總而言之,-g安裝的東西,一般都是用來CMD控制台當命令用。

命令行界面(英語:Command-Line Interface縮寫CLI)是在圖形用戶界面得到普及之前使用最為廣泛的用戶界面,它通常不支持鼠標,用戶通過鍵盤輸入指令,計算機接收到指令后,予以執行。也有人稱之為字符用戶界面CUI)。

 

今后完全可以用cnpm代替npm使用。

 

cnpm install

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM