圖片來源:www.instagram.com/p/BiaH379hr…javascript
在現實生活的開發中,咱們常常須要對新功能進行快速迭代。在本教程中,我將向你展現一些你能夠採起的措施,以提高大約 20% 的開發速度。html
爲何要這樣,你可能會問?前端
由於在編程時進行人工操做每每會很是拔苗助長,咱們但願儘量將流程自動化。所以,我將向你展現使用 Webpack v4.6.0 提高 React 的開發過程當中的哪些部分。java
我不會介紹如何初始化配置 webpack,由於我已經在以前的帖子裏講過它。在那篇文章裏,我詳細介紹瞭如何配置 Webpack。我假設在閱讀本文以前你已經熟悉 Webpack 配置的基礎知識,這樣咱們就能夠從準備好了基本配置以後開始。node
在你的 webpack.config.js
文件中,添加如下代碼:react
// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new CleanWebpackPlugin('dist', {} ),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash()
]
};
複製代碼
並在你的 package.json
文件中添加這些依賴:android
{
"name": "post",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --mode production",
"dev": "webpack --mode development"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-runtime": "^6.26.0",
"clean-webpack-plugin": "^0.1.19",
"html-webpack-plugin": "^3.2.0",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.13",
"webpack-md5-hash": "0.0.6"
}
}
複製代碼
接下來你能夠安裝你的項目所需依賴:webpack
npm i
複製代碼
並將 index.html
和 index.js
兩個文件添加進項目的 src/
目錄下ios
首先在 src/index.html
文件中添加以下代碼:git
<html>
<head>
</head>
<body>
<div id="app"></div>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
</body>
</html>
複製代碼
接着在 src/index.js
中添加:
console.log("hello, world");
複製代碼
執行 dev 腳本:
npm run dev
複製代碼
接下來你就會發現:項目完成編譯了!如今讓咱們繼續爲它配置 React。
因爲 React 使用了名爲 JSX 的特殊語法,咱們須要轉換代碼。若是咱們去 babel 的官網,就能夠看到它爲咱們提供了 React 的 preset.
npm install --save-dev babel-cli babel-preset-react
複製代碼
咱們的 .babelrc
文件應該長這樣:
{
"presets": ["env", "react"]
}
複製代碼
在你的 index.js
文件中添加一些項目的初始化代碼:
import React from 'react';
import { render } from 'react-dom';
class App extends React.Component {
render() {
return (
<div>
'Hello world!'
</div>
);
}
}
render(<App />, document.getElementById('app'));
複製代碼
接着執行 dev 腳本:
npm run dev
複製代碼
若是在你的 ./dist
目錄下可以看到一個 index.html
文件和一個帶有 hash 值的 main.js
文件,那麼說明你作得很棒!項目完成了編譯!
嚴格來講,咱們並非必需要使用它,由於社區裏有不少爲前端服務的 node.js 服務端程序。但我之因此建議使用 webpack-dev-server 由於本就是爲 Webpack 而設計的,它支持一些很好的功能,如熱模塊替換、**Source Maps(源文件映射)**等。
正如他們在官方文檔中提到的那樣:
使用 webpack 和後端開發服務配合可以實現 live reloading(熱重啓),但這隻應當被用於開發環境下。
這可能會讓人感到有些困惑:怎樣使 webpack-dev-server 僅在開發模式下生效?
npm i webpack-dev-server --save-dev
複製代碼
在你的 package.json
文件中,調整:
"scripts": {
"dev": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
複製代碼
如今它應該可以啓動一個本地服務器並使用你的應用程序自動打開瀏覽器選項卡。
你的 package.json
如今看起來應該像這樣:
{
「name」: 「post」,
「version」: 「1.0.0」,
「description」: 「」,
「main」: 「index.js」,
「scripts」: {
"dev": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
},
「author」: 「」,
「license」: 「ISC」,
「devDependencies」: {
「babel-cli」: 「6.26.0」,
「babel-core」: 「6.26.0」,
「babel-loader」: 「7.1.4」,
「babel-preset-env」: 「1.6.1」,
「babel-preset-react」: 「6.24.1」,
「babel-runtime」: 「6.26.0」,
「clean-webpack-plugin」: 「0.1.19」,
「html-webpack-plugin」: 「3.2.0」,
「react」: 「16.3.2」,
「react-dom」: 「16.3.2」,
「webpack」: 「4.6.0」,
「webpack-cli」: 「2.0.13」,
「webpack-dev-server」: 「3.1.3」,
「webpack-md5-hash」: 「0.0.6」
}
}
複製代碼
如今,若是你嘗試修改應用中的某些代碼,瀏覽器就會自動刷新頁面。
接下來,你須要將 React devtools 添加到 Chrome 擴展程序。
這樣,你就能夠更輕鬆地使用 Chrome 控制檯調試應用。
咱們爲何須要它?好吧,一般來說咱們不是必須使用它,但 ESLint 是一個方便的工具。在咱們的例子中,它將呈現並突出顯示(在編輯器和終端中以及在瀏覽器上)咱們代碼中的錯誤,包括拼寫錯誤等等(若是有的話),這稱爲 linting。
ESLint 是一個開源的 JavaScript linting 實用程序,最初由 Nicholas C. Zakas 於 2013 年 6 月開發完成。它有其替代品,但到目前爲止,它與 ES6 和 React 配合使用效果特別好,可以發現常見問題,並能與項目的生態系統其餘部分集成。
如今,讓咱們在本地爲咱們本身的新項目安裝它。固然,此時 ESLint 會有不少設置。你能夠在官方網站閱讀更多相關信息。
npm install eslint --save-dev
./node_modules/.bin/eslint --init
複製代碼
最後一個命令將建立一個配置文件。系統將提示你選擇如下三個選項:
在本教程中,我選擇了第一個:回答問題。如下是個人答案:
這會將一個 .eslintrc.js
文件添加到項目目錄中。我生成的文件以下所示:
module.exports = {
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
};
複製代碼
到目前爲止什麼都沒發生。雖然這是一個徹底有效的配置,但這還不夠,咱們必須將它與 Webpack 和咱們的文本編輯器集成才能工做。正如我所提到的,咱們能夠在代碼編輯器、終端(做爲 linter)或 git 的 precommit 鉤子中使用它。咱們如今將爲咱們的編輯器配置它:
若是你想要,幾乎每一個經常使用的代碼編輯器都有 ESLint 插件,包括 Visual Studio Code、Visual Studio、SublimeText、Atom、WebStorm 甚至是 vim。因此,下載你本身的文本編輯器的對應版本。在本次示例中我會使用 VS Code。
如今咱們能夠看到出現了一些代碼錯誤提示。這是由於項目有一個 Lint 配置文件,它會在沒有遵照某些規則時標記代碼並提示警告。
你能夠經過檢查錯誤消息手動調試它,或者你可使用它只需執行保存便自動修復問題的功能。
你如今也能夠調整 ESLint 設置:
module.exports = {
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"warn",
"single"
],
"semi": [
"error",
"always"
]
}
};
複製代碼
更改了配置以後,若是你錯誤地使用了雙引號而不是單引號,ESLint 不會中斷構建。它還將爲 JSX 添加一些檢查。
Prettier 是當今最流行的格式化程序之一,它已被編碼社區普遍使用。它能夠添加到 ESLint、你的編輯器,也能夠被掛載在 git 的 pre-commit 鉤子上。
我會在這裏將它安裝到個人 VS Code 中
安裝後,你能夠嘗試再次檢查代碼。若是咱們寫一些奇怪的縮進並執行保存,它應該會自動格式化代碼。
但這還不夠。爲了使其與 ESLint 同步工做而且不會兩次發出相同的錯誤,甚至發生規則衝突,你須要將它與 ESLint 集成。
npm i --save-dev prettier eslint-plugin-prettier
複製代碼
在官方文檔中,他們建議你使用 yarn,但 npm 如今一樣也能安裝。在你的 .eslintrc.json
文件中添加:
...
sourceType: "module"
},
plugins: ["react", "prettier"],
extends: ["eslint:recommended", "plugin:react/recommended"],
rules: {
indent: ["error", 2],
"linebreak-style": ["error", "unix"],
quotes: ["warn", "single"],
semi: ["error", "always"],
"prettier/prettier": "error"
}
...
複製代碼
如今咱們想擴展咱們的 ESLint 規則以包含 prettier 的規則:
npm i --save-dev eslint-config-prettier
複製代碼
併爲你的 eslint 配置添加一些 extends:
...
extends: [
"eslint:recommended",
"plugin:react/recommended",
"prettier",
"plugin:prettier/recommended"
]
...
複製代碼
讓咱們爲它添加更多配置。爲了不默認的 Prettier 規則和你的 ESLint 規則之間的不匹配,你應該像我如今這樣作:
Prettier 借用了 ESLint 的 override 格式,這容許你將配置應用於特定的文件。
你如今能夠以 .js
文件的形式爲其建立配置文件。
nano prettier.config.js
複製代碼
如今,粘貼到該文件中:
module.exports = {
printWidth: 80,
tabWidth: 2,
semi: true,
singleQuote: true,
bracketSpacing: true
};
複製代碼
如今,當你執行保存時,你會看到代碼自動格式化。那不是很漂亮(prettier)嗎?雙關語頗有意思。
個人 package.json
文件如今看起來是這樣:
{
"name": "post",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server --mode development --open"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-runtime": "^6.26.0",
"clean-webpack-plugin": "^0.1.19",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-prettier": "^2.6.0",
"eslint-plugin-react": "^7.7.0",
"html-webpack-plugin": "^3.2.0",
"prettier": "^1.12.1",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.13",
"webpack-dev-server": "^3.1.4",
"webpack-md5-hash": "0.0.6"
}
}
複製代碼
如今咱們已經完成了不少工做,讓咱們快速回顧一下:ESLint 會監視代碼中的錯誤,而 Prettier 是一種樣式格式化工具。ESLint 有許多方法能夠捕獲錯誤,而 Prettier 能夠很好地格式化你的代碼。
// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new CleanWebpackPlugin('dist', {} ),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash()
]
};
複製代碼
有些人指出 VS Code 沒法使用 Prettier。
若是你的 Prettier 插件在保存時沒有自動格式化代碼,你能夠經過將下面的代碼添加到 VS Code 設置來修復它:
"[javascript]": {
"editor.formatOnSave": true
}
複製代碼
問題描述在這裏。
因爲 ESLint 是在項目中配置的,所以一旦運行 dev 服務器,它也會在終端中提示警告。
特別提示:儘管能夠這樣作,但此時我不建議將 ESLint 用做 Webpack 的 loader。它將破壞 source map 的生成,我在個人前一篇文章《如何解決 Webpack 中的問題 —— 一些實際案例》中有更詳細的描述。我將展現如何在這裏設置它,以防這些人已經修復了他們的錯誤。
Webpack 有它本身的 ESLint loader.
npm install eslint-loader --save-dev
複製代碼
你必須將 ESLint 添加到 rules 配置中。當使用了使用了編譯類的 loader(如 babel-loader)時,請確保它們的執行順序正確(從下到上)。不然,Webpack 將檢查文件通過 babel-loader 編譯後的文件。
...
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [{ loader: "babel-loader" }, { loader: "eslint-loader" }]
}
]
},
...
複製代碼
如下是你可能遇到的一些問題:
若是你偶然發現了這個錯誤(no-unused-vars),那麼在 GitHub 和這裏的這個 issue 中很好地解釋了這個錯誤。
咱們能夠經過添加一些規則來解決這個問題,這裏和這裏都有解答。
你可能已經注意到,這裏會出現 no-unused-vars 錯誤,你須要將其設爲警告而不是錯誤,由於這樣能夠更輕鬆地進行快速開發。你須要向 ESLint 添加新規則,以便不會收到默認錯誤。
...
semi: ['error', 'always'],
'no-unused-vars': [
'warn',
{ vars: 'all', args: 'none', ignoreRestSiblings: false }
],
'prettier/prettier': 'error'
}
...
複製代碼
這樣咱們就會獲得漂亮的錯誤和警告信息。
我喜歡使用自動修復功能,但咱們必須明確一點:我並非特別想讓事情神奇地改變。爲了不這種狀況,咱們如今能夠提交 autofix。
在使用 Git 工具時,人們都會很是當心。但我向你保證,這個東西很是簡單並且直截了當。掛載了 Prettier 的 Pre commit 鉤子以後,團隊在每一個項目文件中將有一致的代碼風格,而且沒有人能夠提交不規範的代碼。要爲你的項目設置 Git 集成,以下所示:
git init
git add .
nano .gitignore (add your node_modules there)
git commit -m "First commit"
git remote add origin your origin
git push -u origin master
複製代碼
這裏有一些關於 git 鉤子和使用 Prettier 的精彩文章。
對於那些說你只能在本地作這些操做的人說:不,那不是真的!
你可使用 Andrey Okonetchnikov 開源的 lint-staged 工具執行此操做。
讓咱們在咱們的應用程序中建立一個新組件。到目前爲止,咱們的 index.js
看起來像這樣:
import React from 'react';
import { render } from 'react-dom';
class App extends React.Component {
render() {
return <div>Hello</div>;
}
}
render(<App />, document.getElementById('app'));
複製代碼
咱們將建立一個名爲 Hello.js 的新組件用於演示。
import React from 'react';
class Hello extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
export default Hello;
複製代碼
如今在 index.js
文件中引入:
import React from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
class App extends React.Component {
render() {
return (
<div>
<Hello hello={'Hello, world! And the people of the world!'} />
</div>
);
}
}
render(<App />, document.getElementById('app'));
複製代碼
咱們應該看到這個元素,但 ESLint 提示警告:
Error: [eslint] ‘hello’ is missing in props validation (react/prop-types)
在 React v16 中,必須添加 prop 類型以免類型混淆。你能夠在這裏閱讀更多相關信息。
import React from 'react';
import PropTypes from 'prop-types';
class Hello extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
Hello.propTypes = {
hello: PropTypes.string
};
export default Hello;
複製代碼
如今你已經檢查了代碼,如今是時候向 React 應用添加更多組件了。到目前爲止,你只有兩個,但在大多數狀況下,你會有幾十個。
固然,每次更改項目中的某些內容時,從新編譯整個應用程序都不是一種好的選擇,你須要一種更快的方法來優化它。
因此讓咱們添加熱模塊替換,即 HMR。在文檔中,它被描述爲:
熱模塊更換(HMR)在應用程序運行時變動、添加或刪除模塊無需徹底從新加載。能夠經過如下幾種方式顯著提高開發速度:
保留在徹底從新加載期間丟失的應用程序狀態。
只更新已變動的內容,便可節省寶貴的開發時間。
更快地調整樣式 —— 幾乎能夠與在瀏覽器控制檯中進行樣式更改相媲美。
我不會在這裏討論它的工做原理:這足夠寫成一篇單獨的文章,但我會告訴你該如何配置它:
...
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
devServer: {
contentBase: './dist',
hot: true
},
module: {
rules: [
...
複製代碼
咱們必須使用 hash 來替換 chunkhash,由於很明顯 webpack 已經修復了自上次以來的問題,如今咱們終於讓熱模塊替換開始正常工做了!
...
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash].js'
},
devServer: {
contentBase: './dist',
...
複製代碼
若是咱們在這裏運行 dev 腳本:
而後使用這個 issue 提到的方案來解決它:
接下來,在 package.json
中添加 --hot 參數到 dev 腳本中:
...
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server --hot"
}
...
複製代碼
我以前提到過,source maps 不能和 ESLint loader 一塊兒使用,我在這裏提了一個 issue。
一般,你不管如何都不但願它們出如今你的項目中(由於你想從 ESLint 錯誤消息中調試項目),總所周知,他們會使 HMR 變慢。
若是你但願生成 source maps,最簡單的方法就是經過 devtools 選項。
...
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash].js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
hot: true
},
...
複製代碼
注意:你必須以正確的方式配置環境,不然 source maps 將不起做用。你能夠在這裏閱讀個人調試過程。下面我將爲你梳理一個流程並解釋我如何解決該問題。
若是咱們如今在代碼中建立一個錯誤,它將顯示在控制檯中並指向正確的位置:
但現實好像不太盡人意…
這是錯誤的作法
你須要更改環境變量,以下所示:
...
"main": "index.js",
"scripts": {
"build": "webpack --mode=production",
"start": "NODE_ENV=development webpack-dev-server --mode=development --hot"
},
"author": ""
...
複製代碼
webpack.config.js
...
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
open: true
}
...
複製代碼
如今它就有效了!
如你所見,咱們獲得了發生錯誤的確切文件!
如今項目的開發環境已經搭建成功!
讓咱們回顧一下:
特別提醒:因爲許多 npm 依賴項可能會在你閱讀此內容時發生更改,所以相同的配置可能對你無效。我懇請你將錯誤留在下面的評論中,以便我之後編輯。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。