項目初始化
$ npm init
複製代碼
安裝webpack
$ npm install --save-dev
複製代碼
新建webpack配置文件
- 在根目錄建立build文件夾,添加一個js文件,命名爲webpack.base.conf.js
// webpack.base.conf.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
}
};
複製代碼
使用merge的方式來組織webpack基礎配置和不一樣環境的配置
$ npm install --save-dev webpack-merge
複製代碼
- 在build文件夾中再添加一個js文件,命名爲 webpack.prod.conf.js
// webpack.prod.conf.js 文件
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
module.exports = merge(baseWebpackConfig, {
mode: 'production'
});
複製代碼
在根目錄下建立app目錄,而後建立index.js文件
var element =document.getElementById('root');
element.innerHTML = 'hello, world!';
複製代碼
- 在根目錄建立一個public文件夾,而後新建一個index.html文件
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>從零開始搭建react工程</title>
</head>
<body>
<div id="root"></div>
<script src="../dist/js/bundle.js"></script>
</body>
</html>
複製代碼
當前項目目錄樹
|- /app
|- index.js
|- /node_modules
|- /public
|- index.html
|- /build
|- webpack.base.conf.js
|- webpack.prod.conf.js
|- package.json
|- package-lock.json
複製代碼
安裝webpack-cli
- webpack 4.0 版本以後的webpack,已經將webpack命令工具遷移到webpack-cli模塊了,須要安裝 webpack-cli
$ npm install --save-dev webpack-cli
複製代碼
package.json文件 scripts屬性配置一個build命令
- 其值爲:webpack --config build/webpack.prod.conf.js,如下是scripts的相關代碼
// package.json
"scripts": {
"build": "webpack --config build/webpack.prod.conf.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
複製代碼
安裝React
$ npm install --save react react-dom
複製代碼
import React from "react";
import ReactDom from "react-dom";
ReactDom.render(
<h1>hello, world!</h1>,
document.getElementById("root")
);
複製代碼
- 注意 import 屬於ES6規範,所以須要轉譯ES2015+的語法,安裝並配置 babel 以及相關依賴
$ npm install --save-dev babel-loader babel-core babel-preset-env babel-preset-react
複製代碼
- 根目錄建立.babelrc文件,配置presets.
{
"presets": [
[
"env",
{
"targets": {
"browsers": [
"> 1%",
"last 5 versions",
"ie >= 8"
]
}
}
],
"react"
]
}
複製代碼
// webpack.base.conf.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
}
]
}
};
複製代碼
添加插件
- public下的index.html本該自動添加到dist目錄,而且引用資源自動加載到該文件,經過html-webpack-plugin實現這一步
$ npm install html-webpack-plugin --save-dev
複製代碼
- webpack.prod.conf.js中配置plugins屬性
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
mode: 'production',
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
})
]
});
複製代碼
- 刪除 index.html 中手動引入的 script 標籤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>從零開始搭建react工程</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
複製代碼
- 從新編譯查看 npm run build 瀏覽器打開查看目錄 dist 下的 index.html
以上步驟都成功的前提下繼續走下一步
- 生成的文件名添加Hash值,目的是解決緩存問題
- 修改webpack.prod.conf.js,mode: 'production', 增長如下代碼
// webpack.prod.conf.js
output: {
filename: "js/[name].[chunkhash:16].js",
},
複製代碼
- 生成前須要清理以前項目生成的文件,由於因爲文件名的改變若是不刪除會一直增長
- 安裝插件 clean-webpack-plugin
$ npm install --save-dev clean-webpack-plugin
複製代碼
// webpack.prod.conf.js
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
mode: 'production',
output: {
filename: "js/[name].[chunkhash:16].js",
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
}),
new CleanWebpackPlugin(['../dist'], { allowExternal: true })
]
});
複製代碼
公共代碼與業務代碼分離
- 修改 webpack.base.conf.js 的 entry 入口屬性,抽出框架代碼
entry: {
app: './app/index.js',
framework: ['react','react-dom'],
},
複製代碼
- 修改webpack.prod.conf.js,增長如下代碼,目的是分離框架代碼和業務代碼
- 雖然上面步驟抽出框架代碼生成兩個文件,可是app.js仍是包含框架代碼
optimization: {
splitChunks: {
chunks: "all",
minChunks: 1,
minSize: 0,
cacheGroups: {
framework: {
test: "framework",
name: "framework",
enforce: true
}
}
}
}
複製代碼
- cacheGroups對象,定義了須要被抽離的模塊
- 其中test屬性是比較關鍵的一個值,他能夠是一個字符串,也能夠是正則表達式,還能夠是函數。若是定義的是字符串,會匹配入口模塊名稱,會從其餘模塊中把包含這個模塊的抽離出來
- name是抽離後生成的名字,和入口文件模塊名稱相同,這樣抽離出來的新生成的framework模塊會覆蓋被抽離的framework模塊
整合 webpack-dev-server
$ npm install --save-dev webpack-dev-server
複製代碼
- 在build中添加webpack.dev.conf.js文件
const path = require('path');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = merge(baseWebpackConfig, {
mode: 'development',
output: {
filename: "js/[name].[hash:16].js",
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
minify: {
html5: true
},
hash: false
}),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
port: '8080',
contentBase: path.join(__dirname, '../public'),
compress: true,
historyApiFallback: true,
hot: true,
https: false,
noInfo: true,
open: true,
proxy: {}
}
});
複製代碼
- 在package.json scripts屬性添加內容
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
複製代碼
- npm run dev
- 自動打開瀏覽器打開入口頁面實時更新
獨立導出 css 文件
$ npm install extract-text-webpack-plugin
$ npm install style-loader css-loader postcss-loader autoprefixer --save-dev
$ npm install less sass less-loader sass-loader stylus-loader node-sass --save-dev
複製代碼
- webpack.base.conf.js 文件修改
// webpack.base.conf.js
{
test: /\.css$/,
use: [
{
loader: "style-loader" //在html中插入<style>標籤
},
{
loader: "css-loader",//獲取引用資源,如@import,url()
},
{
loader: "postcss-loader",
options: {
plugins:[
require('autoprefixer')({
browsers:['last 5 version']
})
]
}
}
]
},
{
test:/\.less$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{
loader: "postcss-loader",//自動加前綴
options: {
plugins:[
require('autoprefixer')({
browsers:['last 5 version']
})
]
}
},
{ loader: "less-loader" }
]
},
{
test:/\.scss$/,
use:[
{ loader: "style-loader" },
{
loader: "css-loader",
},
{ loader: "sass-loader" },
{
loader: "postcss-loader",
options: {
plugins:[
require('autoprefixer')({
browsers:['last 5 version']
})
]
}
}
]
},
複製代碼
$ npm i file-loader url-loader --save-dev
複製代碼
- webpack.base.conf.js 文件修改
// webpack.base.conf.js
{
test: /\.(png|jpg|gif|woff|svg|eot|woff2|tff)$/,
use: 'url-loader?limit=8129',
//注意後面那個limit的參數,當你圖片大小小於這個限制的時候,會自動啓用base64編碼圖片
exclude: /node_modules/
}
複製代碼
build 時報錯
Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
at Chunk.get (F:\react\createApp\node_modules\webpack\lib\Chunk.js:824:9)
複製代碼
- webpack4.0中使用「extract-text-webpack-plugin」報錯
- 解決辦法
$ npm install extract-text-webpack-plugin@next
複製代碼
背景圖片路徑問題
- 因爲css文件分離出來的緣由,會致使在css文件夾下找images文件夾下的圖片
- 解決辦法 publicPath屬性改成 '/',以絕對路徑的方式尋找資源
{
test:/\.(png|jpg|gif)$/,
use:[{
loader:'url-loader',
options: {
// outputPath:'../',//輸出**文件夾
publicPath: '/',
name: "images/[name].[ext]",
limit:500 //是把小於500B的文件打成Base64的格式,寫入JS
}
}]
},
複製代碼