自己寫的 React, Webpack 練習,
練習了以下 webpack loader:
sass-loader :
用來處理編譯 sass 檔案。
css-loader :
用來處理 css 檔案。
style-loader :
用來將 css 寫進網頁中 (不用在網頁中另寫 <link rel="stylesheet" href="xxx.css" />)。
image-webpack-loader :
用來處理圖片檔案,有圖片壓縮等功能。
url-loader :
用來將圖片的 url 寫進網頁中,內部使用了 file-loader,所以可使用 file-loader 的選項參數,
有能把圖片的 url 轉成 base64 url 的等功能。
mini-css-extract-plugin :
用來把處理好的 css 輸出成最後版本 css 檔案的功能,
網頁要使用 css 需自行加入 css style include, Ex:
<link rel="stylesheet" href="xxx.css" />)
實作了一個簡易的 tab 選單當範例來練習:
1. 有三個選單 tab,分別對應三個內容 (暫稱 content),內容中有各自的文字及各放置了不同的圖片。
2. 當滑鼠滑入 tab 中時 (mouseenter) ,下方會切換到對應的 Content。
檔案結構如下圖所示:
重要的程式碼如下 (以下根目錄以從 package.json 檔所在位置,也就是 WebContent 資料夾算起):
/index.html :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="root"></div>
<script src="dist/js/index_bundle.js"></script>
</body>
</html>
/dev/js/index.jsx :
import React from "react"
import ReactDOM from "react-dom"
import {Main} from "./components/Main.jsx"
import "@projectDirPath/dev/css/style.scss"
ReactDOM.render(<Main/>, document.getElementById("root"));
/dev/js/components/Main.jsx :
import React from "react"
import {Tab} from "./Tab.jsx"
import {Content} from "./Content.jsx"
import dogImgSrc from "@projectDirPath/dev/img/dog.jpg"
import catImgSrc from "@projectDirPath/dev/img/cat.jpg"
import bananaCatImgSrc from "@projectDirPath/dev/img/bananaCat.jpg"
function Main(){
const [itemList, setItemList] = React.useState([
{
title: "title1",
desc: "desc1",
img: dogImgSrc,
isActive: true
},
{
title: "title2",
desc: "desc2",
img: catImgSrc,
isActive: false
},
{
title: "title3",
desc: "desc3",
img: bananaCatImgSrc,
isActive: false
}
]);
function setItemActive(index){
var updatedItemList = itemList.map((item, i) => {
item.isActive = (i == index);
return item;
});
setItemList(updatedItemList);
}
return (
<React.Fragment>
<div className="tab">
{
itemList.map((item, index) => {
return <Tab item={item} key={index} index={index} setItemActive={setItemActive}/>;
})
}
</div>
<div className="content">
{
itemList.map((item, index) => {
return <Content item={item} key={index}/>;
})
}
</div>
</React.Fragment>
)
}
export {Main}
/dev/js/components/Content.jsx :
import React from "react"
function Content({item}){
return (
<div className={item.isActive ? "active" : ""}>{item.desc}<img src={item.img}/></div>
);
}
export {Content}
/dev/js/components/Tab.jsx :
import React from "react"
function Tab({item, index, setItemActive}){
function handleMouseEnter(){
setItemActive(index);
}
return (
<div className={item.isActive ? "active" : ""} onMouseEnter={handleMouseEnter}>{item.title}</div>
);
}
export {Tab}
/dev/css/style.scss :
.tab {
div {
display: inline-block;
width: 30%;
height: 100px;
background-color: green;
background-color: yellow;
border-bottom: 3px solid black;
}
div.active {
background-color: yellow;
border-left: 3px solid black;
border-right: 3px solid black;
border-top: 3px solid black;
border-bottom: 3px solid yellow;
}
}
.content {
background-color: yellow;
border-left: 3px solid black;
border-right: 3px solid black;
border-bottom: 3px solid black;
div {
display: none;
padding: 3px;
}
div.active {
display: block;
}
img {
width : 30%;
}
}
webpack.config.js:
var path = require('path');
//const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry : "./dev/js/index.jsx",
output : {
path : path.resolve(__dirname, "dist"),
filename : "js/index_bundle.js",
publicPath : "dist/"
},
resolve: {
alias: {
'@projectDirPath': __dirname
}
},
watch : false,
devtool : 'source-map',
mode : "development", //"production",
module : {
rules : [ {
test : /\.jsx?$/,
use : {
loader : 'babel-loader',
options : {
presets : [ '@babel/preset-react', '@babel/preset-env' ]
}
}
},
{
test: /\.(png|jpg|gif|jpe?g|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 50 * 1024,
outputPath: "img"
}
},
"image-webpack-loader"
]
},/*
{
test : /\.css$/,
use : ["style-loader", "css-loader"]
},*/
{
test: /\.s[ac]ss$/,
use: [
"style-loader", //MiniCssExtractPlugin.loader,
"css-loader", "sass-loader"
]
}]
}
//, plugins: [new MiniCssExtractPlugin()]
}
package.json
{
"name": "reacttest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"runServer": "lite-server"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.5",
"@babel/preset-env": "^7.7.5",
"@babel/preset-react": "^7.7.4",
"babel-loader": "^8.0.6",
"css-loader": "^5.0.1",
"file-loader": "^6.2.0",
"image-webpack-loader": "^7.0.1",
"lite-server": "^2.6.1",
"mini-css-extract-plugin": "^1.3.3",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.2.2",
"redux": "^4.0.5"
}
}
原始碼分享下載:
參考:




