初始化項(xiàng)目
$ npm init
webpack配置
- 創(chuàng)建基于webpack4.42.1版本
$ yarn add webapck webapck-cli webpack-dev-server -D
通過yarn add <package...> [--dev/-D]
會(huì)安裝到devDependencies
對(duì)象下瞻想。
通過yarn add <package...>
會(huì)安裝到dependencies
對(duì)象下膏蚓。
在這里解釋下devDependencies
和dependencies
:
devDependencies
對(duì)象下通常是構(gòu)建工具需要的包霜威,比如:loader,plugin等呛牲。
而dependencies
是需要打包到靜態(tài)文件的包,比如:react,lodash等狼速。
新建webpack基礎(chǔ)配置文件
- 在根目錄創(chuàng)建 build 文件夾,
webpack.base.conf.js
文件 - 在根目錄創(chuàng)建 src 文件夾卦停,添加
main.js
文件
// webpack.base.conf.js 文件
const path = require('path');
// 處理路徑
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// 入口
entry: {
app: "./src/main.js",
},
// 出口
output: {
filename: "[name].js",
path: "dist"
},
resolve: {
// https://webpack.js.org/configuration/resolve/#resolveextensions
extensions: ['.js', '.jsx','.tsx','.json'],
// https://webpack.js.org/configuration/resolve/#resolvealias
alias: {
'@': resolve('src'),
'public': resolve('public'),
}
},
};
不同環(huán)境的配置
這里我們需要 webpack-merge
包來(lái)合并不同環(huán)境的配置
$ yarn add webpack-merge -D
在根目錄創(chuàng)建build文件夾向胡,添加生產(chǎn)環(huán)境 webpack.prod.conf.js 文件與開發(fā)環(huán)境webpack.dev.conf.js 文件
// webpack.prod.conf.js 文件
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
module.exports = merge(baseWebpackConfig, {
mode: 'production'
});
// webpack.dev.conf.js 文件
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
module.exports = merge(baseWebpackConfig, {
mode: 'development'
});
安裝React
$ yarn add react react-dom
- 在src目錄下的main.js添加代碼如下
import React from "react";
import ReactDom from "react-dom";
ReactDom.render(
<h1>hello, world!</h1>,
document.getElementById("root")
);
添加loader與plugin
babel
$ yarn add @babel/core @babel/preset-env @babel/preset-react babel-loader -D
- 根目錄創(chuàng)建.babelrc文件,配置presets
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"> 1%",
"last 5 versions",
"ie >= 8"
]
}
}
],
[
"@babel/preset-react"
]
],
}
- 修改webpack.base.conf.js文件
// webpack.base.conf.js 文件
const path = require('path');
// 處理路徑
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// 入口
entry: {
app: "./src/main.js",
},
// 出口
output: {
filename: "[name].js",
path: "dist"
},
resolve: {
// https://webpack.js.org/configuration/resolve/#resolveextensions
extensions: ['.js', '.jsx','.tsx','.json'],
// https://webpack.js.org/configuration/resolve/#resolvealias
alias: {
'@': resolve('src'),
'public': resolve('public'),
},
module: {
rules: [
{
test: /\.js?$/,
use: "babel-loader",
include: resolve('src')
}
]
}
},
};
css
$ yarn add less less-loader css-loader mini-css-extract-plugin postcss-loader -D
mini-css-extract-plugin
已經(jīng)支持HMR了惊完,所以不再需要style-loader做開發(fā)模式兼容;
- 根目錄下創(chuàng)建
postcss.config.js
// postcss.config.js
module.exports = {
plugins: {
'autoprefixer': {
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8"
]
}
}
}
// webpack.base.conf.js 文件
const path = require('path');
// 處理路徑
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// 入口
entry: {
app: "./src/main.js",
},
// 出口
output: {
filename: "[name].js",
path: "dist"
},
resolve: {
// https://webpack.js.org/configuration/resolve/#resolveextensions
extensions: ['.js', '.jsx','.tsx','.json'],
// https://webpack.js.org/configuration/resolve/#resolvealias
alias: {
'@': resolve('src'),
'public': resolve('public'),
},
module: {
rules: [
{
test: /\.js?$/,
use: "babel-loader",
include: resolve('src')
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// only enable hot in development
hmr: true,
// if hmr does not work, this is a forceful method.
reloadAll: true
}
},
"css-loader",
"postcss-loader"
]
},
{
test: /\.less$/,
include: [resolve("src"), resolve("node_modules/antd")],
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// only enable hot in development
hmr: true,
// if hmr does not work, this is a forceful method.
reloadAll: true
}
},
{
loader: "css-loader" // translates CSS into CommonJS
},
{
loader: "less-loader", // compiles Less to CSS
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'images/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
]
}
},
};
靜態(tài)文件
$ yarn add url-loader file-loader -D
// webpack.base.conf.js 文件
const path = require('path');
// 處理路徑
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// 入口
entry: {
app: "./src/main.js",
},
// 出口
output: {
filename: "[name].js",
path: "dist"
},
resolve: {
// https://webpack.js.org/configuration/resolve/#resolveextensions
extensions: ['.js', '.jsx','.tsx','.json'],
// https://webpack.js.org/configuration/resolve/#resolvealias
alias: {
'@': resolve('src'),
'public': resolve('public'),
},
module: {
rules: [
{
test: /\.js?$/,
use: "babel-loader",
include: resolve('src')
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'images/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
]
}
};
以上就是就是base文件所有配置;
配置dev文件
$ yarn add html-webpack-plugin -D
- 根目錄下創(chuàng)建public文件夾僵芹,創(chuàng)建一個(gè)
index.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>從零開始搭建react腳手架</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
- 開啟 webpack-dev-server
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");
const config = require("../config");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devWebpackConfig = merge(baseWebpackConfig, {
mode: "development",
output: {
filename: "js/[name].[hash:16].js"
},
devtool: "source-map",
devServer: {
port: '8080',
contentBase: path.join(__dirname, '../public'),
compress: true,
historyApiFallback: true,
hot: true,
https: false,
noInfo: true,
open: true,
proxy: {}
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: "public/index.html",
inject: "body",
minify: {
html5: true
}
}),
new MiniCssExtractPlugin({
// 生成對(duì)應(yīng)的css文件
filename: "[name].css",
chunkFilename: "[id].css",
ignoreOrder: true
}),
// 文件更改后重新頁(yè)面
new webpack.HotModuleReplacementPlugin(),
]
});
以上就完成了開發(fā)環(huán)境的配置
配置prod文件
$ yarn add optimize-css-assets-webpack-plugin clean-webpack-plugin terser-webpack-plugin uglifyjs-webpack-plugin -D
生產(chǎn)模式下通常都是配置些壓縮文件的插件,有興趣的童鞋可以到npm查查這些包的使用
const config = require('../config')
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')小槐;
const TerserJSPlugin = require('terser-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
mode: 'production',
output: {
filename: "js/[name].[chunkhash:16].js",
chunkFilename: "js/[id].[chunkhash].js",
path: "dist",
},
optimization: {
// 壓縮文件
minimizer: [new TerserJSPlugin({}), new OptimizeCSSPlugin({})],
},
plugins: [
// 壓縮JS
new UglifyJsPlugin({
uglifyOptions: {
warnings: false
},
parallel: true
}),
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
}),
// 該插件會(huì)根據(jù)模塊的相對(duì)路徑生成一個(gè)四位數(shù)的hash作為模塊id
new webpack.HashedModuleIdsPlugin(),
// 這個(gè)插件會(huì)在 webpack 中實(shí)現(xiàn)以上的預(yù)編譯功能拇派。
new webpack.optimize.ModuleConcatenationPlugin(),
new MiniCssExtractPlugin({
filename: "css/[name].[hash:7].css",
chunkFilename: "css/[id].[hash:7].css",
ignoreOrder:true
}),
// 刪除舊dist目錄
new CleanWebpackPlugin(),
]
});
以上就完成了生產(chǎn)環(huán)境的配置
配置 package.json
// package.json
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build": "webpack --config build/webpack.prod.conf.js",
},
運(yùn)行 yarn dev
本地調(diào)試 react
代碼,運(yùn)行 yarn build
可對(duì)項(xiàng)目進(jìn)行打包了凿跳;