1. 程式人生 > >從零配置Webpack4.0搭建一個React工程

從零配置Webpack4.0搭建一個React工程

最近一直大部分精力都在搞App以及Node。前端這塊作為初心,還是不能落下。這裡不用cli。一步一步記錄從零配置Webpack,來搭建起React專案。複習一下Webpack的配置。以及一些前端工程化的一些思考

前段工程化思考

說道前端工程化,最重要的一個目的就是:解放生產力。對原始碼進行預處理、自動打包/自動更新頁面顯示、去處理圖片依賴和正式環境統一這幾點在開發中極大提高了開發的效率。在搭建起專案工程之後開發人員只需要關注業務/程式碼即可。第二點就是保證專案質量,在多人協作,不同環境下開發。通過code lint等約束以及git commit預處理保證程式碼風格的一致統一,這一點對後續的程式碼維護很重要。第三就是優化。通過前端工程化、自動化去合理的壓縮合並資原始檔。這些大部分恰巧webpack幫我們完成了。
在vue和react開發中,通過腳手架工具,生成專案之後,只要run一下專案就跑起來了。然而cli給我們提供的只是一個泛模板。然而我們想要去定製它、修改它。就需要深入瞭解它,知道他是怎麼跑起來的。我想考慮的前端工程化,這是每一個前端er繞不開的話題。坑越早開越好>_<

Webpack基礎配置

這裡首先我們要明確webpack工程架構的核心是什麼?
– loader機制 (不同loader去處理不同的檔案。甚至你可以自己創造一個檔案,並作出對應的loader來處理它)

首先 我們npm init建立一個專案。接下來安裝初始化需要的依賴:

npm i react --save
npm i react-dom --save
npm i webpack --save
npm i webpack-cli --save

最基本的依賴包安裝完畢之後,我們需要建立WebApp的入口檔案。這裡我們在根目錄建立一個src資料夾,並建立兩個空檔案app.js(作為入口檔案) 以及App.jsx(宣告我們app頁面上的內容)。
有了入口檔案,就可以進行Webpack的基本配置。這裡我們在根目錄下建立build資料夾在下面webpack.config.js裡進行配置:


const path = require('path') // 引入‘path’,為了在這裡使用絕對路徑,避免相對路徑在不同系統時出現不必要的問題

module.exports ={
  // 應用入口
  entry: {
    app: path.join(__dirname, '../src/app.js')  // app.js作為打包的入口
  },
  // 輸出目錄
  output: {
    filename: '[name].[hash].js',  //name代表entry對應的名字; hash代表 整個app打包完成後根據內容加上hash。一旦整個檔案內容變更,hash就會變化
    path: path.join(__dirname, '../dist'), // 打包好之後的輸出路徑
    publicPath: '/public' // 靜態資原始檔引用時的路徑(加在引用靜態資源前面的)
  }

有了入口和輸出。我們就可以啟動webpack了。這裡在app.js隨便寫一段簡單的js程式碼執行:

webpack --config build/webpack.config.js --mode development

為了方便我們把這段程式碼加到script裡:

"build": "webpack --mode development --config build/webpack.config.js"

(Webpack4 不新增mode,會有:The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.警告。對應option:development or production)

就會在專案根目錄下多出一個dist資料夾。裡面就是壓縮打包好的程式碼

Webpack Loader基礎

我們要處理.jsx以及.js檔案。這裡我們就需要在上面的webpack.config.js加入新配置

// 配置loader
module: {
  rules: [
    {
      test: /.jsx$/, //使用loader的目標檔案。這裡是.jsx
      loader: 'babel-loader'
    },
    {
      test: /.(js)$/, //使用loader的目標檔案。這裡是.js
      loader: 'babel-loader',
      exclude: [
        path.join(__dirname, '../node_modules')  // 由於node_modules都是編譯過的檔案,這裡我們不讓babel去處理其下面的js檔案
      ]
    }
  ]
}

這裡我們用babel-loader處理jsx檔案。光在這裡配置不想我們需要安裝一些依賴
babel-loader以及babel-core(這是babel的核心處理程式碼)。有了這些我們在app.js和App。jsx寫一個最簡單的react程式碼:

//app.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'

ReactDOM.render(<App />, document.body)

//App.jsx
import React from 'react'

export default class App extends React.Component {
  render () {
    return (
      <div>this is app</div>
    )
  }
}

執行一下npm run build,發現報錯。這是因為我們沒有進行babel的配置。在根目錄加上一個.babelrc的檔案

{
  "presets": [
    ["es2015", {"loose": true}],
    "react"
  ]
}

並安裝相關依賴:babel-preset-es2015、babel-preset-es2015-loose(這個是寬鬆模式)、babel-preset-react。

再次build,dist資料夾就會出現新打包的js檔案咯

生成一個HTML

這裡我們想要在dist資料夾生成一個html頁面去檢視 我們處理過後的js程式碼可不可以用。這裡我們需要藉助’html-webpack-plugin’這個plugin

npm i html-webpack-plugin -D

在webpack.config.js裡新增

const HTMLPlugin = require('html-webpack-plugin')

以及底部追加:

plugins: [
  new HTMLPlugin()   // 生成一個html頁面,同時在webpack編譯的時候。把我們所生成的entry都注入到這個html頁面中,路徑都是根據我們output配置的來走的。
]

另外不要忘了 將output配置中的publicPath設為空,便於我們測試。

上面步驟走完,我們在build一下,發現dist資料夾中多出來了一個index.html檔案。

開啟測試一下。發現我們的chrome上出現了“this is app”的字樣 ~搞定!

React服務端渲染配置

現在單頁面應用大行其道的年代,為了解決SEO不友好以及首屏過長的紋理。服務端渲染(SSR)也是繞不開的。
react-dom是react專供web端開發渲染的工具。而服務端沒有window/document等屬性:ReactDOM.render( , document.body)這句是用不了的。

下面就來說說node服務端執行環境程式碼在webpack下怎麼搞定:
首先我們需要在src目錄下建立一個server渲染的入口

//server-entry.js
import React from 'react'
import App from './App.jsx'

export default <App />

之後在build中在區別開web端的webpack配置,另外建立一個新的配置檔案暫且叫:webpack.config.server.js大部分內容都和web端的配置一樣:

const path = require('path') // 引入‘path’,為了在這裡使用絕對路徑,避免相對路徑在不同系統時出現不必要的問題

module.exports ={
  target: 'node', //webpack打包出來的內容使用在什麼環境下
  // 應用入口
  entry: {
    app: path.join(__dirname, '../src/server-entry.js')  // app.js作為打包的入口
  },
  // 輸出目錄
  output: {
    filename: 'server-entry.js',  // node端沒有瀏覽器快取這個概念,並且需要在node中直接import這個檔案。故直接命名就好
    path: path.join(__dirname, '../dist'), // 打包好之後的輸出路徑
    publicPath: '',
    libraryTarget: 'commonjs2' // 打包出來js模組所使用的方案(umd、amd、cmd、commonJS)這裡我們使用commonjs2,適用於node端
  },
  // 配置loader
  module: {
    rules: [
      {
        test: /.(jsx)$/, //使用loader的目標檔案。這裡是.jsx
        loader: 'babel-loader'
      },
      {
        test: /.(js)$/, //使用loader的目標檔案。這裡是.js
        loader: 'babel-loader',
        exclude: [
          path.join(__dirname, '../node_modules')  // 由於node_modules都是編譯過的檔案,這裡我們不讓babel去處理其下面的js檔案
        ]
      }
    ]
  }
}

值得注意的就是我們需要加上target和output中libraryTarget這兩個配置。
之後改一下我們的npm script:

"build:web": "webpack --mode development --config build/webpack.config.js",
"build:server": "webpack --mode development --config build/webpack.config.server.js",
"clear": "rimraf dist",
"build": "npm run clear && npm run build:web && npm run build:server"

(rimraf是一個非常好用刪除資料夾的庫,當然也可以用rm的方式)

npm run build

走一波。發現dist多出了server-entry.js這個打包好的檔案。打開秋一眼,有別於web打包(是一個自執行的方法)。

已經變成了node模組匯出的方式咯。
這裡我們用express搭建一個服務,看看是否成功:

const express =require('express')
const ReactSSR = require('react-dom/server')
const serverEntry = require('../dist/server-entry').default
const app = express()

app.get('*', (req, res) => {
  const appStr = ReactSSR.renderToString(serverEntry)
  res.send(appStr)
})

app.listen(2333, () => {
  console.log('server is listening on 2333')
})

react SSR這塊不是這篇blog的重點就不細說。這裡需要注意的是。我們的server-entry是通過export default匯出的與import配套。在node中用require的方式需要require(‘../dist/server-entry’).default一下
這一塊的知識點可以看阮一峰老師寫的博文

啟動伺服器:

chrome上出現:this is app

搞定!

新增html模板

然而我們會發現,我們通過服務端渲染出來的只是:

顯然不是我們想要的,二來,之前我們將直接掛在在body上其實也是不對的。這裡我們迫切需要一個html模板。
在src下建立一個template.html檔案:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
    <div id="root"><!--app--></div>
</body>
</html>

更改webpack.config.js配置,在HTMLPlugin中新增選項:

new HTMLPlugin({
  template: path.join(__dirname, '../src/template.html') // 以template.html作為模板檔案生成html
})

因為牽扯靜態檔案。web端和werver端webpack的配置:輸出目錄中的publicPath: ‘public’

當然app.js中就需要掛載在root節點上了。ReactDOM.render( , document.getElementById(‘root’))

說完web端,再搞服務端。在server.js中改為:

const express =require('express')
const fs = require('fs')
const ReactSSR = require('react-dom/server')
const serverEntry = require('../dist/server-entry').default
const path = require('path')
const tplPath = path.join(__dirname, '../dist/index.html')
const template = fs.readFileSync(tplPath, 'utf8') // 不指定utf-8,預設是buffer
const app = express()

app.use('/public', express.static(path.join(__dirname, '../dist'))) //靜態檔案指定請求返回

app.get('*', (req, res) => {
  const appStr = ReactSSR.renderToString(serverEntry)
  res.send(template.replace('<!--app-->', appStr))
})

app.listen(2333, () => {
  console.log('server is listening on 2333')
})

因為改了之前的程式碼,我們需要重新build一下再啟動服務

npm run build && node server/server.js

這就出來了

最後 :

告訴我們服務端渲染,需要用這個react16新加的這個方法ReactDOM.hydrate()
大概意思就是如果我們使用了服務端渲染,我們需要用ReactDOM.hydrate(),在web端去渲染內容。react回去對比客戶端和服務端生成的程式碼
之間的差別。如果有差別,他會用客戶端的程式碼替換掉服務端的程式碼。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'

ReactDOM.hydrate(<App />, document.getElementById('root'))

再走一波就沒有警告了。

webpack-dev-server

webpack dev server是一個通過webpack配置啟動的server

配置起來也很簡單。
首先:

npm i webpack-dev-server -D

之後需要判斷是否為開發環境

const isDev = process.env.NODE_ENV === 'development'

將webpack.config.js中的moudle.exports,拿出來。賦值為const config
之後:

if (isDev) {
  config.devServer = {
    host: '0.0.0.0',  // 我們可以允許我們用任意方式進行訪問(127.0.0.1,localhost, 本機ip)
    port: '8888',
    contentBase: path.join(__dirname, '../dist'),
    // hot: true,  //啟動熱載入
    overlay: {  // 錯誤提醒彈窗小遮層
      errors: true //只顯示error
    },
    // 和output配置對應起來
    publicPath: '/public',  // 訪問所有靜態路徑都要前面加/public才能訪問生成的靜態檔案
    historyApiFallback: {
      index: '/public/index.html' // 所有404的請求全部訪問該配置下的url
    }
  }
}

module.exports = config

之後啟動可以使用這條命令:

cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js --mode development

其中cross-env也需要安裝。這裡他是為了解決mac下(*nix)和win環境變數設定不一致這個問題。
執行完畢,http://localhost:8888/就可以使用了

相關推薦

配置Webpack4.0搭建一個React工程

最近一直大部分精力都在搞App以及Node。前端這塊作為初心,還是不能落下。這裡不用cli。一步一步記錄從零配置Webpack,來搭建起React專案。複習一下Webpack的配置。以及一些前端工程化的一些思考前段工程化思考說道前端工程化,最重要的一個目的就是:解放生產力。對

手把手教你認識webpack4.0

原文連結:https://www.jianshu.com/p/f931f47cbf75 前言: 作為一個現代javascript 應用程式的靜態模組打包器,webpack能將各種資源,如js,css, 圖片等作為模組來處理,是當下前端工程化的一個很受歡迎的工具,webpack目前最新的版本是4.0,文章將在

開始用 Flask 搭建一個網站(一)

前言 筆者之前未接觸過 Python,只是略懂一點前端,所以說從零開始也相差無幾吧。Flask 是一個輕量級的基於 Python 的框架,但是擴充套件性非常良好(Github 上 22000 多個 star 就知道群眾的選擇不無道理),其他的這裡就不多提了,下

webpack4配置搭建簡單的React16開發環境

scripts cif TBase ase ren 如果 輸出 init ntb 寫在最前 暑假想要學習React, 發現React官網上的沒有說明如何搭建React開發環境, 網上找的很多都是基於webpack3的, 或者直接使用腳手架, 所以趁著放假, 就稍微學了下we

webpack4學習(React)--重點細節整理筆記(Webpack 4 教程:配置到生產釋出--http://www.css88.com)

一、開始配置webpack4開發環境   cmd開啟操作介面 mkdir 檔名 && cd 檔名   ------建立專案並進入專案目錄 npm init -y   ------初始化建立package.json檔案,-y的意思是初始化時全部選擇yes,

react開發:開始搭建一個react專案

從頭開始建立一個React App - 專案基本配置 npm init 生成 package.json 檔案.安裝各種需要的依賴: npm install --save react - 安裝React.npm install --save reac

開始用webpack4.x建立一個react(三)

webpack都已經配置好了,我們現在要來將react引入 因為react用到的是jsx語法,所以我們要用到babel 執行 `npm i babel-core [email protected] babel-plugin-transform-runtime -

不使用 vue-cli 與 vue 模版,使用 Vue2.x + webpack4.x 開始一步步搭建專案框架

說明 這是我根據慕課網上的一個課程 Vue+Webpack打造todo應用 過程一步步搭下來的框架,去掉了業務相關的邏輯。 專案最終的效果包括了引入vue框架;使用CSS前處理器;使用babel;引用圖片等靜態資源;區分開發環境與生成環境,並做相應優化等。基本接近真正做專案時候的配置

開始使用 webpack5 搭建 react 專案

> 本文的示例專案原始碼可以點選 [這裡](https://github.com/jacob-lcs/react-webpack5-template) 獲取 ## 一、前言 webpack5 也已經發布一段時間了,其模組聯邦、bundle 快取等新特性值得在專案中進行使用。經過筆者在公司實際專案中的升級結

如何開始用Keras開發一個機器翻譯系統

參考: https://yq.aliyun.com/articles/475854?utm_content=m_42632 #load doc into memory def load_doc(filename):     #open the file a

使用qemu模擬器搭建arm執行環境

為什麼會有這篇文章 早在2011年的時候,跟當時同事一起討論,做Linux系統開發正處於整個linux開發中間層,沒有上層的C/C++業務和資料庫的開發經驗,也沒有底層的核心和驅動開發經驗,到底路該如何走……基於對Linux系統開發的理解和核心的興趣,認為選擇Linux核心開發更適合自己。於

如何手動使用webpack搭建一個react專案

前言搭一個腳手架真不是一件容易的事,之前為了學習webpack是怎麼配置的選擇自己搭建開發環境,折騰了好幾天總算對入口檔案、打包輸出、JSX, es6編譯成es5、css載入、壓縮程式碼等這些基礎的東西有了一個大體的瞭解。 大體專案結構(模仿網上大佬)   然後就是正題了,當然最先要做的是

到有模擬實現一個Set類

前言 es6新增了Set資料結構,它允許你儲存任何型別的唯一值,無論是原始值還是物件引用。這篇文章希望通過模擬實現一個Set來增加對它的理解。 原文連結 用在前面 實際工作和學習過程中,你可能也經常用Set來對陣列做去重處理 let unique = (array

webpack4.0搭建vue教程

webpack4.0 的使用 參考連結 1.建立目錄結構 沒有安裝記得先安裝webpack npm install webpack webpack-cli -D 2.使用 npm init -y 來生成配置是檔案 package.json 3.1 使用命令打包 npx webpack ./src/m

開始建立初始化一個vue2的專案

對於前端小白甚至是沒怎麼接觸過前端的小夥伴們,這篇關於vue2入門的文章,正是為你量身定做,好了,廢話不多說mm~ 我的電腦需要安裝一些亂七八糟的軟體麼? NO!!你只是要安裝node中的npm包管理器,那麼,該怎麼安裝呢?開啟https://nodej

2018年終:一次起步的產品搭建的思考

在我整個職業生涯裡,運營依舊是主要內容,無論是活動運營,內容運營,抑或是產品運營都沒有特別能讓我有多少成就感的地方,或者是想讓運營有成就感的事情辦起來其實太難了。在更多人的眼裡運營就是一個釘子,只要保證負責的模組不出問題那就是最好了,但是往往對運營的要求遠比當個產品和技術要來的高。 坊間說天下運營是一家,無

開始在伺服器搭建Hexo部落格

也可以點選該連結:http://106.12.200.86/post/5454b416.html#more 一、開發環境 ubuntu16.04 node.js github Windows10 64bits 二、在本地Windows上搭建He

學習RxJava2.0-簡單入門

前言 函數語言程式設計:函數語言程式設計是種程式設計方式,它將電腦運算視為函式的計算。函式程式語言最重要的基礎是λ演算(lambda calculus),而且λ演算的函式可以接受函式當作輸入(引數)

配置雲伺服器(Java web執行環境)(二、配置JAVA開發環境)

二、配置JAVA開發環境 先進入我們的實力列表,右邊進入遠端連線。 這裡遠端連線1 輸入遠端連線密碼後連線成功,接著輸入系統登陸賬號密碼。(Unix系統輸入密碼都是不顯示在螢幕上的,是連小星星都沒有的。) 登陸成功後我們先新建一個目錄

開始Eclipse/Maven搭建SSM框架做web應用(超詳細+100%可用+避坑版)

目前SSM框架(Spring+SpringMVC+Mybatis)依然是市場主流,如何搭建一個實用的SSM框架是很多同學都想學習的技能。但網路上的大多數教程要麼不完整,要麼還遺留了很多坑,即使嚴格按教程來也很難得到我們想要的結果。所以我就想自己寫一篇搭建攻略,即使零基礎的同學,按我的攻略步驟