一個現(xiàn)代JS Web項目開發(fā)環(huán)境其實就是一個Nodejs應用,通過使用一系列工具完成開發(fā)過程中的各種任務,所以,現(xiàn)在完成一個項目的開發(fā)不能只是敲代碼,還必須掌握一些現(xiàn)代的工程方法和工具。本文對于常用的一些工具和方法進行簡單整理。
基礎工具和概念
包管理
通常JS項目的開發(fā)都是從安裝依賴包開始的,就是執(zhí)行npm i xxx命令。實際使用中,最好使用cnpm代替npm,速度快很多,出錯情況也少。安裝時要區(qū)分3中情況:dependencies(-S或--save),devDependencies(-D或--save-dev),peerDependencies?。這3種方式都會把包安裝在node_modules目錄下,但是在package.json中在相應字段對象中。
dependencies是生產(chǎn)環(huán)境依賴的包,devDependencies是開發(fā)環(huán)境依賴的包。如果開發(fā)的項目是最終的應用,其實看不出這兩種方式有什么區(qū)別,但是如果開發(fā)的是會被其他項目依賴的庫,執(zhí)行install時,只有dependencies被安裝,devDependencies不被安裝。
如果自己做的庫需要依賴某個包A,但是又不想在被其他項目引用時在自己的目錄下安裝包A,而是使用項目中的包A,那么就把這個包放在peerDependencies里。這中方式主要是為了解決版本一致性和靜態(tài)初始化的問題。這個和Nodejs查找node_modules的規(guī)則有關,在尋找NPM模塊包時,會從當前目錄出發(fā),向上搜索各級當中的node_modules文件夾當中的文件,但若有兩個同名文件,則遵循就近原則。這樣就可能會導致整個應用使用某個包的版本不一致。如果包A里有靜態(tài)初始化的代碼(例如:創(chuàng)建一個全局對象),這樣會導致多次執(zhí)行,產(chǎn)生沖突。
參考:https://docs.npmjs.com/files/package.json
參考:https://nodejs.org/dist/latest-v10.x/docs/api/modules.html
Babel
Babel是一個Javascript編譯器,通過插件( plugin)對處理代碼。Babel的插件非常多,用preset代表插件的集合。
插件是npm里的一個包,在Babel的配置文件中直接指定包名。
{
"plugins": ["babel-plugin-myPlugin"]
}
插件的名稱如果以babel-plugin-開頭,可以省略。
{
"plugins": ["myPlugin"]
}
如果設置了多個插件或preset,執(zhí)行的順序是:
- 插件優(yōu)先于預制;
- 插件按從前到后執(zhí)行;
- 預制按從后到前執(zhí)行。
插件和預制都可以指定參數(shù)。
{
"plugins": [["pluginA", {}]]
}
參考:https://babeljs.io/docs/en/babel-cli/
prettier
prettier是一個代碼格式化工具,可以設置行寬度、縮進空格數(shù)、結尾分號等。
參考:https://prettier.io/docs/en/options.html
ESLint
ESLint是一個插件話的Javascript代碼檢查工具,可以輔助發(fā)現(xiàn)代碼的語法和格式問題。
cnpm i eslint -D # 安裝
eslint --init # 初始化
ESLint 默認使用Espree作為其解析器,你可以在配置文件中指定一個不同的解析器,例如:Babel-ESLint。
{
"parser": "esprima",
"rules": {
"semi": "error"
}
}
一個環(huán)境定義了一組預定義的全局變量。
{
"env": {
"browser": true,
"node": true
}
}
ESLint 附帶有大量的規(guī)則。你可以使用注釋或配置文件修改你項目中要使用的規(guī)則。要改變一個規(guī)則設置,你必須將規(guī)則 ID 設置為下列值之一:
- "off" 或 0 - 關閉規(guī)則
- "warn" 或 1 - 開啟規(guī)則,使用警告級別的錯誤:warn (不會導致程序退出)
- "error" 或 2 - 開啟規(guī)則,使用錯誤級別的錯誤:error (當被觸發(fā)的時候,程序會退出)
{
"rules": {
"eqeqeq": "off",
"curly": "error",
"quotes": ["error", "double"]
}
}
設置信息可以放在.eslintrc.js文件或者package.json文件中的eslintConfig部分。
參考:https://eslint.bootcss.com/docs/user-guide/configuring/
webpack
webpack 是一個現(xiàn)代 JavaScript 應用程序的靜態(tài)模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
loader讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript),例如:style-loader,css-loader,file-loader等。loader 可以將所有類型的文件轉換為 webpack 能夠處理的有效模塊,然后你就可以利用 webpack 的打包能力,對它們進行處理。
插件目的在于解決 loader 無法實現(xiàn)的其他事,例如生成html文件(HtmlWebpackPlugin),限制chunk的大小,進行資源替換等。
從 webpack v4.0.0 開始,可以不用引入一個配置文件。
從頭設置新項目
從0開始
創(chuàng)建項目目錄。
mkdir try-vscode
初始化,創(chuàng)建默認的package.json文件。
npm init -y
在項目目錄下創(chuàng)建.vscode/settings.json文件,用于vscode的項目本地化設置。
{
"editor.detectIndentation": false,
"editor.tabSize": 2
}
設置代碼格式化
安裝插件Prettier - Code formatter
創(chuàng)建.prettierrc文件
{
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 120
}
也可以將這些設置放在.vscode/settings.json中。
{
"prettier.semi": false,
"prettier.singleQuote": true,
"prettier.printWidth": 120,
"prettier.tabWidth": 2
}
代碼檢查
安裝(如果已經(jīng)進行了全局安裝可以不進行本地安裝)
cnpm i eslint -S
初始化配置文件.eslintrc.js
npx eslint --init
按提示進行選擇
? How would you like to use ESLint? To check syntax and find problems
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? None of these
? Where does your code run? (Press <space> to select, <a> to toggle all, <i> to invert selection)Browser, Node
? What format do you want your config file to be in? JavaScript
設置完成后,在VSCode的代碼窗口和problem窗口中就會提示發(fā)現(xiàn)的錯誤。
發(fā)布npm包
需要在npmjs.com注冊賬號,然后通過npm adduser命令添加賬號到本地。
在項目根目錄下執(zhí)行命令。
npm publish
發(fā)布包的內容在package.json文件中定義,主要的字段包括:name,version,files,main,module等。如果package.json中存在 module 字段,會優(yōu)先使用,如果沒找到對應的文件,則會使用 main 字段,并按照 CommonJS 規(guī)范打包。每一次發(fā)布包必須升級版本號,不能直接更新已有版本。
VUE項目
如果VUE的前端項目,最好直接用vue-cli創(chuàng)建項目,這樣就不用單獨安裝依賴包了。
vue-cli create try-vscode
項目創(chuàng)建成功后,會生成package.json和vue.config.js文件(創(chuàng)建項目過程中可以將其他設置指定為獨立的文件)。
如果項目的目錄結構比較復雜,引用代碼的層級較深,可以考慮在vue.config.js文件中設置別名。
chainWebpack: config => {
config.resolve.alias.set('@', resolve('./'))
}
jest.config.js
{
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1'
}
}