從零搭建webpack4+React工程(一)
搭建一個React工程的方式有很多,官方也有自己的腳手架,如果你和我一樣,喜歡刨根究底,從零開始自己一行一行代碼創建一個React項目工程,那你就來對地方了。本教程是針對React新手,以及對webpack還不熟悉的用戶,或者是想了解當前前端工程化方案的用戶。我會在整個系列通過webpack4的配置,postcss等插件引入,代碼壓縮,css編譯,本地代理,環境配置,React技術棧代碼上傳發布都有一個講解。
前提條件
在開始之前,請確保安裝了 Node.js 的最新版本。建議使用 Node.js 最新的長期支持版本(LTS - Long Term Support)。如果你使用舊版本,你可能遇到各種問題,因為它們可能缺少 本教程用到的相關的 package 包。
執行以下命令可以查看你本機安裝的node版本:
node -v && npm -v
如果你本機的node版本不是最新的,建議升級到新的node版本。node版本建議通過nvm進行管理,了解可以查看 http://nvm.sh 這裡不再闡述。
通過本課程,你會學到什麼?
學習完本教程,你將會了解:
- 當前前端開發的框架,工程化的方式
- webpack4的基礎配置以及常用的一些插件
- postcss的使用,以及常用的postcss插件
- 如何更好地配置項目目錄結構
- 如何整合Redux,Flux
- 如何整合mock,以及常用的mock開源框架
- 前端是如何和後端工程師進行介面聯調
- 如何規範代碼,整合eslint。
- 如何測試React代碼
廢話不多說,現在正式開始這個專題的分享。
1.從空文件夾開始
現在創建一個空的文件夾,用你的開發工具打開它。
打開終端,確保你已經進入剛剛創建的目錄,接下去執行:
npm init
終端會讓你輸入一些信息,比如名字,版本,描述,入口文件等等。 完成後,npm會自動在你的根目錄生成 package.json 文件。package.json 文件不僅僅包含項目的配置信息(比如名稱、版本、許可證等元數據),還會記錄項目所需要的各種模塊,以及項目運行的腳本等等。
2.安裝webpack4以及配置
本教程使用webpack來管理react工程。
執行以下命令,安裝webpack
npm install --save-dev webpack
npm安裝的包會存放在一個叫node_modules文件夾。如果你用的npm版本是npm 5版本,你還會發現多了package-lock.json文件。package-lock.json文件是當 node_modules 或 package.json 發生變化時自動生成的文件,它的主要功能是確定當前安裝的包的依賴,以便後續重新安裝的時候生成相同的依賴,而忽略項目開發過程中有些依賴已經發生的更新(翻譯自官方說明)。
打開package.json,你會發現多了一個名為devDependencies的屬性,通過--save-dev安裝的包會記錄在此屬性下。後續我們還會使用--save去安裝一個模塊包,區別是通過--save安裝的模塊會記錄在dependencies屬性內,而不是devDependencies屬性。通過字面意思,你應該也可以知道,一個是dev開發時候的依賴,一個是運行時的依賴。
新建webpack配置文件。webpack 的配置文件,是導出一個對象的 JavaScript 文件。在根目錄創建config文件夾,添加一個js文件,命名為webpack.base.js。 手動敲入以下代碼:
const path = require(path);const DIST_PATH = path.resolve(__dirname, ../dist);module.exports = { entry: { app: ./app/index.js }, output: { filename: "js/bundle.js", path: DIST_PATH }};
webpack 配置是標準的 Node.js CommonJS 模塊,它通過require來引入其他模塊,通過module.exports導出模塊,由 webpack 根據對象定義的屬性進行解析。
這裡定義了2個屬性。當然,webpack的配置屬性遠遠不止這2個,之後我會深入講解更多屬性的配置。回到我們定義的2個屬性,entry定義了入口文件,output定義了編譯後的輸出。按照對這段代碼的理解,它應該是告訴webpack,我這個項目入口文件是app目錄下的index.js文件,你編譯後,在根目錄下創建dist文件夾(如果不存在),最後把編譯後的文件輸出到dist文件下,命名為bundle.js。
webpack4.0還增加了mode屬性,用來表示不同的環境。
我們使用merge的方式來組織webpack基礎配置和不同環境的配置。
先安裝webpack-merge:
npm install --save-dev webpack-merge
在config文件夾中再添加一個js文件,命名為webpack.prod.js,輸入以下代碼。
const merge = require(webpack-merge);const baseWebpackConfig = require(./webpack.base.js);module.exports = merge(baseWebpackConfig, { mode: production});
在根目錄下創建app目錄,然後創建index.js文件。
var element =document.getElementById(root);element.innerHTML = hello, world!;
在根目錄創建一個public文件夾,然後新建一個index.html文件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>從零開始搭建react工程</title></head><body><script src="../dist/bundle.js"></script></body></html>
你現在的文件路徑應該看起來是這樣:(顯然我們引用的bundle.js並不存在)
|- /app |- index.js|- /node_modules|- /public |- index.html|- /config |- webpack.base.js |- webpack.prod.js|- package.json|- package-lock.json
接下去我們要通過執行webpack命令,來編譯我們的代碼,生成bundle.js。4.0版本之後的webpack,已經將webpack命令工具遷移到webpack-cli模塊了。你需要安裝webpack-cli。
npm install --save-dev webpack-cli
安裝完成後,執行下面腳本進行編譯:
webpack --config config/webpack.prod.js
編譯完成後,刷新根目錄,可以看到已經生成dist文件夾和bundle.js文件。
用瀏覽器打開html文件,你會看到hello webpack。我們成功通過webpack編譯了js文件,並且沒有出現問題。
webpack --config config/webpack.prod.js命令,我們可以通過npm scripts管理起來。
在package.json文件,我們為scripts屬性配置一個build命令,其值為:webpack --config config/webpack.prod.js,以下是scripts的相關代碼:
"scripts": { "build": "webpack --config config/webpack.prod.js", "test": "echo "Error: no test specified" && exit 1" },
然後在命令行輸入:
npm run build
我們可以看到,webpack重新進行了編譯,這和執行
webpack --config config/webpack.config.js
是一樣的效果。
3.安裝react
在終端輸入以下命令:
npm install --save react react-dom
安裝成功後,我們在項目使用react,我們直接修改app目錄下的index.js的代碼,我們用react來插入這句hello world!
import React from reactimport ReactDom from react-domReactDom.render(<h1>hello, world!</h1>, document.getElementById(root));
好了,我們再編譯試試看。
npm run build
失敗了?對不對!首先,我告訴你這段代碼沒有任何問題,你需要思考下,它為什麼會編譯失敗。下一小節,我們一起來了解下原因。
4.整合babel
為什麼會失敗?因為webpack只識別JavaScript文件,而且只能編譯es5版本的JavaScript語法。實際上,我們使用ES2015,以及jsx的語法糖,webpack它根本不認識啊。怎麼辦?webpack 可以使用 loader 來預處理文件。它不僅僅可以處理JavaScript本身,還允許你打包任何的靜態資源。
其中,babel-loader,就是這樣一個預處理插件,它載入 ES2015+ 代碼,然後使用 Babel 轉譯為 ES5。我們來了解下如何在webpack配置babel-loader。
首先安裝babel相關的模塊:
npm install --save-dev babel-loader babel-core babel-preset-env babel-preset-react
除了babel-loader,我們還安裝了好多的包,其中babel-core是babel的核心模塊,babel-preset-env是轉譯ES2015+的語法,babel-preset-react是轉譯react的JSX以及FLOW。了解詳情可以移步 babel官方。
第二步,你需要在根目錄建立一個.babelrc的文件,配置相關的presets:
{ "presets": [ [ "env", { "targets": { "browsers": [ "> 1%", "last 5 versions", "ie >= 8" ] } } ], "react" ]}
第三步,修改webpack.base.js文件。
const path = require(path);const APP_PATH = path.resolve(__dirname, ../app);const DIST_PATH = path.resolve(__dirname, ../dist);module.exports = { entry: { app: ./app/index.js }, output: { filename: js/bundle.js, path: DIST_PATH }, module: { rules: [ { test: /.js?$/, use: "babel-loader", include: APP_PATH } ] }};
在 webpack 配置中定義 loader 時,要定義在 module.rules 中。其中,test和use屬性是必須的。include屬性,定義了rules執行的範圍。這告訴 webpack 編譯器如下信息:
嘿,webpack 編譯器,你在編譯文件過程中,如果這個是在app目錄下的js文件,在你對它打包之前,先使用 babel-loader 轉換一下。
重新執行本地編譯
npm run build
這次不再報錯,編譯成功。
好了,再次打開public目錄的index.html,頁面成功顯示了hello world。
可能,你還有一些疑惑,html文件如何也同步到dist目錄?bundle.js文件修改了,萬一被瀏覽器緩存了怎麼辦?如何通過script標籤把打包生成的js自動添加到html?react和業務代碼如何分開打包?如何實現開發環境的熱更新?
下一章,我將針對這些問題,會一一進行講解。
推薦閱讀:
※webpack 配置中的路徑
※Fis3構建遷移Webpack之路
※VUX v2.2.0 發布,基於 WeUI 的 Vue 移動端組件庫
※Webpack自動化構建實踐指南
※如何使用webpack新建項目(以vue為例)