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借鑑於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的時候,有幾個坑務必要注意!!!
<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),這個也許能夠進行一些優化,可是生產環境咱們追求再也不是時間,而是文件體積和加載速度等,感興趣的童鞋能夠本身研究一下~