webpack4配置react(開發環境)

安裝依賴包

npm init // 新建一個package.json文件
npm i -D webpack webpack-cli webpack-dev-server  // 安裝webpack相關
npm i --save react react-dom // 安裝react
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react // 安裝babel相關
npm i -D html-webpack-plugin // 生成html文件
複製代碼

這裏簡單介紹一下babelhtml

babel-loadervue

babel的編譯器,提供轉碼API,好比transform,babel-loader會直接調用babel-core API對文件進行轉碼。node

@babel/corereact

文件轉碼器,簡單的說就是將es6 es7轉換爲讓瀏覽器識別es5。webpack

這裏麪包括了babel 的核心 api,好比 transform,主要都是處理轉碼的。它會把咱們的 js 代碼,抽象成 ast,即 abstract syntax tree(抽象語法樹) 的縮寫,是源代碼的抽象語法結構的樹狀表現形式。咱們能夠理解爲,它定義的一種分析 js 語法的樹狀結構。也就是說 es6 的新語法,跟老語法是不同的,那咱們怎麼去定義這個語法呢。因此必需要先轉成 ast,去發現這個語法的 kind,分別作對應的處理,才能轉化成 es5.es6

@babel/preset-envweb

能夠根據配置的目標運行環境自動啓用須要的babel插件,例如對支持的瀏覽器進行配置:ajax

{
  "targets": {
    "chrome": "58",
    "ie": "11"
  }
}
複製代碼

能夠在.babelrc文件對babel進行配置。 更多須要瞭解babel的請點擊這裏chrome

項目目錄

webpack.dev.conf.jsnpm

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 生成html模板

const resolve = (dir) => path.join(__dirname, '..', dir);

module.exports = {
  mode: 'development', // webpack4新增屬性,默認返回production,提供一些默認配置,例如cache:true
  devtool: 'cheap-module-eval-source-map',
  // source-map每一個module生成對應的map文件
  // eval 每個module模塊執行eval,不生成map文件,在尾部生成一個sourceURL對應先後關係,因此更快
  // cheap 列信息 VLQ編碼
  // module 包含了模塊之間的sourcemap
  entry: {
    home: './src/index.js', // 設置入口文件
  },
  output: {
    filename: '[name].js', // 生成的js文件的名字
    path: resolve('dist'), // 生成的js存放目錄
  },
  module: { // 配置loader
    rules: [
      {
        test: /\.m?js$/,
        include: resolve('src'), // 只解析src下面的文件,不推薦用exclude
        use: {
          loader: 'babel-loader',
        }
      },
    ],
  },
  devServer: { // 配置webpack-dev-server, 在本地啓動一個服務器運行
    host: 'localhost', // 服務器的ip地址 但願服務器外能夠訪問就設置 0.0.0.0
    port: 8088, // 端口
    open: true, // 自動打開頁面
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: resolve('/dist/index.html'), // 生成的html文件存放的地址和文件名
      template: resolve("/index.html"), // 基於index.html模板進行生成html文件
    }),
  ]
}
複製代碼

index.js

import ReactDOM from 'react-dom';
import React from 'react';

ReactDOM.render(
  <h1>表白任素汐!</h1>,
  document.getElementById('root')
)
複製代碼

.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
  ]
}
複製代碼

index.html

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>

  <body>
    <div id='root'>
    </div>
  </body>

</html>
複製代碼

在package.json的scripts添加命令

"dev": "webpack-dev-server --config build/webpack.dev.conf.js",
複製代碼

最後在命令行啓動,一個最簡單的react項目配置好了。

npm run dev
複製代碼

模塊熱更新

webpack經過watch實現熱更新,其實就是將咱們最後一次修改的時間記錄下來,而後定時去監測咱們文件的修改時間,發現二者不同,webpack就會本身去從新建立,咱們能夠設置監測的間隔時間,以及發現了不一樣,延長多久去從新構建。(詳見webpack WatchOptions

若是改變頁面內容,整個頁面都會刷新,可是若是模塊不少的話,編譯就會很慢。模塊熱更新就是檢測代碼有沒有修改,只將修改的模塊進行從新編譯,並替換掉以前的模塊,這樣只有改變的模塊纔會更新,就像ajax同樣局部刷新。

npm install react-hot-loader
npm i -D @babel/plugin-proposal-class-properties // 這個是針對es6 class進行添加的,由於咱們新建了home.js文件用了class
複製代碼

修改webpack.dev.conf.js

devServer: {
    hot: true, // 設置熱更新(引用react熱更新必須設置)
 },
 plugins: [
    new webpack.HotModuleReplacementPlugin(), // 引入熱更新插件(引用react熱更新必須設置),
 ]
複製代碼

.babelrc修改成

{
  "presets": [
    "@babel/preset-react",
    "@babel/preset-env"
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "react-hot-loader/babel"
  ]
}
複製代碼

新建一個home.js

import React, { Component } from 'react';
import { hot } from 'react-hot-loader';

class App extends Component {
  state = {  }
  render() {
    return (
     <h1>表白任素汐!</h1>
    );
  }
}
export default hot(module)(App);
複製代碼

修改index.js

import ReactDOM from 'react-dom';
import React from 'react';
import App from './home';

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
複製代碼

npm run dev看看效果吧~

dllplugin 加速神器

隨着項目愈來愈大,咱們開發調試的時候,最但願的是節省時間,儘量快的進行編譯。dllplugin借鑑於windows的dll文件,咱們能夠把一些項目不會改動的存放在一個文件中,每次webpack進行從新編譯的時候,咱們就能夠直接加載,而不用再進行從新編譯,就像react,react-dom等項目包。

按照這個思路咱們咱們再添加一個webpack.dll.config.js文件

const path = require('path')
const webpack = require('webpack')
// 生產環境不用dll的緣由是由於不少相同的內容會重複打包的bundles裏面
module.exports = {
  entry: {
    vendor: ['react', 'react-dom']
  },
  output: {
    path: path.join(__dirname, '..', 'dist/vendor'), 
    filename: '[name].dll.js',
    library: '[name]_[hash]'
    // vendor.dll.js中暴露出的全局變量名。
    // 主要是給DllPlugin中的name使用,
    // 故這裏須要和webpack.DllPlugin中的name,保持一致。
  },
  //在給定的 path 路徑下建立一個名爲 manifest.json 的文件。 這個文件包含了從 require 和 import 的request到模塊 id 的映射。 DLLReferencePlugin 也會用到這個文件。
  plugins: [
    new webpack.DllPlugin({
      context: __dirname,
      // 定義打包的公共vendor文件對外暴露的函數名
      name: '[name]_[hash]',
      // manifest.json文件的輸出位置
      path: path.join(__dirname, '..', 'dist/vendor/manifest.json')
    })
  ]
}
複製代碼

webpack.dev.conf.js添加

devServer: {
    contentBase: resolve('dist'),  // 設置服務器從那個目錄提供內容,默認當前 推薦使用絕對路徑。
},
 plugins: [
    new HtmlWebpackPlugin({
      filename: resolve('/dist/index.html'), // 生成的html文件存放的地址和文件名
      template: resolve("/index.html"), // 基於index.html模板進行生成html文件
      vendor: './vendor/vendor.dll.js',
    }),
    new webpack.DllReferencePlugin({
      context: __dirname, // 跟dll.config裏面DllPlugin的context一致
      manifest: require(path.join(__dirname, '..', 'dist', '/vendor/manifest.json')),
    }),
  ],
複製代碼

在配置dllplugin的時候,有幾個坑務必要注意!!!

  • webpack.dll.config.js中,output的library和new webpack.DllPlugin的name務必保持一致!
  • webpack.dev.conf.js中new webpack.DllReferencePlugin的執行上下文context必須和webpack.dll.config.js中的context保持一致!
  • devserver中必須設置contentBase靜態文件指向!這裏咱們把打包出來的vendor.dll.js文件放在了dist文件夾下面。
  • 須要在index.html文件中引入vendor.dll.js文件,利用html-webpack-plugin獲取設置的vendor屬性
<script src="<%= htmlWebpackPlugin.options.vendor %>"></script>
複製代碼

咱們在package.json的scripts中添加命令行:

"dev_dll": "webpack --config build/webpack.dll.config.js",
複製代碼

執行dev_dll就能夠在看到打包好的vendor.dll.js文件

npm run dev_dll
複製代碼

咱們再執行npm run dev,咱們能夠看到delegated ... from dll-reference的打包引用,就說明了dllplugin引用成功了

[./node_modules/_react-dom@16.6.3@react-dom/index.js] delegated ../node_modules/_react-dom@16.6.3@react-dom/index.js from dll-reference vendor_3b82321a4a4ec9fad65d 42 bytes {home} [built]
複製代碼

隨着項目的豐富,咱們能夠把更多的不改動的三方包放在vendor.dll.js中,預計能夠給項目帶來30—40%的速度提高!

寫在最後,dllplugin追求的是開發調試的時候儘量減小webpack編譯的時間,官方不推薦放在production中使用,一方面是dllplugin會打包重複代碼(好比在vue項目中elementui,dllplugin會重複打包vue),這個也許能夠進行一些優化,可是生產環境咱們追求再也不是時間,而是文件體積和加載速度等,感興趣的童鞋能夠本身研究一下~

相關文章
相關標籤/搜索