首先初始化項(xiàng)目
npm init
一脏嚷、安裝webpack
要安裝最新版本或特定版本,請(qǐng)運(yùn)行以下命令之一:
npm install --save-dev webpack
npm install --save-dev webpack@<version>
如果你使用 webpack 4+ 版本,你還需要安裝 CLI羽德。
npm install --save-dev webpack-cli
二几莽、新建文件目錄
mkdir ./src ./public ./src/components
vim ./src/index.js
vim ./src/components/HellowWord.js
vim ./public/index.html
# 文件目錄格式
|-- Webpack
|-- package-lock.json
|-- package.json
|-- webpack.config.js
|-- public
|-- src
|-- index.js
<!-- public/index.js-->
<body>
<div id="app"></div>
</body>
// src/index.js
import React from "react";
import HelloWorld from "./components/HellowWorld";
class App extends React.Component {
render() {
return <HelloWorld />;
}
}
ReactDOM.render(<App />, document.getElementById("app"));
// src/components/HelloWorld.js
import React from "react";
export default class App extends React.Component {
render() {
return <h1>Hello World</h1>;
}
}
三、配置加載器
3.1 構(gòu)建簡(jiǎn)單的webpack.common.js
配置文件
根據(jù)上述文件目錄結(jié)構(gòu)宅静,新建配置文件 public/webpack.common.js
const path = require("path");
const webpack = require("webpack");
function resolve(dir) {
return path.join(__dirname, "..", dir);
}
module.exports = {
entry: "./src/index.js",
output: {
path: util.resolve("dist"),
filename: "[name].js",
chunkFilename: "[chunkhash].js",
jsonpFunction: "myWebpackJsonp"
}
};
在packge.json
添加
"scripts": {
"dev": "webpack --config ./build/webpack.common.js"
},
嘗試運(yùn)行npm run dev
ERROR in ./src/index.js 7:11
Module parse failed: Unexpected token (7:11)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| class App extends React.Component {
| render() {
> return <HelloWorld />;
| }
| }
webpack
告訴我們需要使用加載器來處理該文件章蚣,針對(duì) react 文件,需要使用babel-loader
姨夹,對(duì)于其他的格式文件纤垂,需要進(jìn)行配置。
由于配置中會(huì)用到一些工具磷账,所以新建/build/util.js
峭沦,引入util.js
const path = require("path");
//返回項(xiàng)目根目錄下的dir路徑
exports.resolve = function resolve(dir) {
return path.join(__dirname, "..", dir);
};
//返回dits中文件路徑下的dir路徑
exports.staticPath = function resolve(dir) {
return path.join("static/", dir);
};
3.2 配置babel-loader
npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react
在webpack.config.js
添加 babel 配置
...
module: {
rules: [
{
test: /\.js?$/,
include: [util.resolve('src')],
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
}
]
}
...
3.3 配置.css
.scss
文件 loader
sass-loader
依賴node-sass
,由于這個(gè)包存放在 github 上逃糟,下載速度比較慢吼鱼,可使用淘寶源下載
npm install sass-loader node-sass css-loader style-loader --save-dev --registry https://registry.npm.taobao.org
在webpack.config.js
rules 添加配置
...
{
test: /\.css$/,
use: [{ loader: "style-loader" }, { loader: "css-loader" }]
},
{
test: /\.scss$/,
use: [
{ loader: "style-loader" }, // 將 JS 字符串生成為 <style> 節(jié)點(diǎn)
{ loader: "css-loader" }, // 將 CSS 轉(zhuǎn)化成 CommonJS 模塊
{ loader: "sass-loader" } // 將 Sass 編譯成 CSS
]
}
...
3.4 配置圖片文件的加載
關(guān)于圖片或文件的相關(guān)loader
:
file-loader
默認(rèn)情況下,生成的文件的文件名就是文件內(nèi)容的 MD5 哈希值并會(huì)保留所引用資源的原始擴(kuò)展名履磨。url-loader
功能類似于 file-loader蛉抓,但是在文件大小(單位 byte)低于指定的限制時(shí)剃诅,可以返回一個(gè) DataURL巷送。?? 注意url-loader
依賴file-loader
這里選擇使用url-loader
npm install --save-dev url-loader file-loader
在webpack.config.js
rules 添加配置
...
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 6000,
name: util.staticPath('images/[name][hash].[ext]'),
}
}
]
}
...
四、開發(fā)環(huán)境構(gòu)建
區(qū)分production
和 development
環(huán)境下的配置
vim ./build/webpack.dev.js ./build/webpack.prod.js
4.1 安裝相關(guān)功能依賴
# 用于合并webpack配置
npm install --save-dev webpack-merge
# 分別用于構(gòu)建時(shí)清除dist目錄和拷貝處理index.html
npm install --save-dev clean-webpack-plugin html-webpack-plugin
# 用于啟動(dòng)開發(fā)服務(wù)器
npm install webpack-dev-server -D
# 用于開發(fā)時(shí)模塊熱重載
npm install hot-module-replacement-plugin -D
# 產(chǎn)品模式壓縮js
npm install uglifyjs-webpack-plugin -D
# 提取css矛辕、壓縮css(替代ExtractTextWebpackPlugin)
npm install mini-css-extract-plugin -D
# 注入process.env變量
npm install cross-env -D
?? 需要注意的是:在 css 文件的loader
配置中MiniCssExtractPlugin.loader
與style-loader
不能同時(shí)使用笑跛。
const devMode = process.env.NODE_ENV !== 'production'
...
{
test: /\.css$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
"css-loader"
]
},
{
test: /\.scss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
{ loader: "css-loader" }, // 將 CSS 轉(zhuǎn)化成 CommonJS 模塊
{ loader: "sass-loader" } // 將 Sass 編譯成 CSS
]
},
...
修改webpack.prod.js
...
plugins: [
new HtmlWebpackPlugin({
template: util.resolve('public/index.html'),
filename: util.resolve('dist/index.html'),
favicon: util.resolve('public/favicon.ico')
}),
],
resolve: {
extensions: [".js", ".json", ".jsx", ".css"],
alias: {
'@': util.resolve('src')//路徑別名 可添加 jsconfig.json 配合編輯器提供路徑提示功能
}
},
...
分別添加webpack.prod.js
webpack.dev.js
文件
webpack.prod.js
const merge = require("webpack-merge");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const common = require("./webpack.common.js");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = merge(common, {
mode: "production",
plugins: [
new UglifyJSPlugin(),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: util.staticPath("style/[name].css"),
chunkFilename: util.staticPath("style/[id].css")
})
]
});
webpack.dev.js
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
const webpack = require("webpack);
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
devServer: {
contentBase: "./dist"
},
pluging: [new webpack.HotModuleReplacementPlugin()]
});
4.2 修改scripts
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./build/webpack.dev.js"
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.js"
現(xiàn)在執(zhí)行npm run dev
將會(huì)得到一個(gè)簡(jiǎn)單的開發(fā)環(huán)境
五、功能的進(jìn)一步完善
到此為止我們完成了一個(gè)簡(jiǎn)單的配置聊品,在開發(fā)環(huán)境下實(shí)現(xiàn)熱重載飞蹂、加載樣式文件,生產(chǎn)環(huán)境下代碼壓縮翻屈、自動(dòng)拷貝index.html
并注入script
陈哑、打包自動(dòng)清理dist
文件夾。下面繼續(xù)完善相關(guān)的功能伸眶。
配置devserver
配置如下惊窖,命令行只顯示警告或錯(cuò)誤信息,同時(shí)使用friendly-errors-webpack-plugin
插件厘贼,自動(dòng)清除信息界酒,并自定義顯示信息內(nèi)容。
npm install -D friendly-errors-webpack-plugin
webpack.dev.js
const devServerConfig = {
contentBase: util.resolve("dist"),
clientLogLevel: "warning",
port: 3000,
hot: true,
host: "localhost",
open: false,
quiet: true,
overlay: {
/**
* Shows a full-screen overlay in the browser
* when there are compiler errors or warnings.
*/
warnings: false,
errors: true
},
proxy: {
// detail: https://www.webpackjs.com/configuration/dev-server/#devserver-proxy
"/base": {
target: "https://test.cn",
secure: true,
changeOrigin: true,
pathRewrite: {
"^/base": ""
}
}
}
};
module.exports = merge(common, {
mode: "development",
plugins: [
new webpack.DefinePlugin({
"env.PRODUCTION": "false"
}),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin(),
new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [
`You application is running here http://${devServerConfig.host}:${devServerConfig.port}`
]
},
clearConsole: true
})
],
devServer: devServerConfig,
devtool: "source-map"
});
配置buils.js
文件
安裝依賴
npm install -D chalk ora
新建build/build.js
嘴秸,修改scripts.build
cross-env NODE_ENV=production node ./build/build.js
毁欣,ora
是一個(gè)在命令行顯示的加載動(dòng)畫庇谆,chalk
能夠輸出帶有顏色的文字或消息。
const webpack = require("webpack");
const webpackConfig = require("./webpack.prod");
const ora = require("ora");
const chalk = require("chalk");
const spinner = ora("buildind...");
spinner.start();
webpack(webpackConfig, (err, stats) => {
spinner.stop();
if (err) throw err;
process.stdout.write(
stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + "\n\n"
);
if (stats.hasErrors()) {
console.log(chalk.red(" Build failed with errors.\n"));
process.exit(1);
}
console.log(chalk.cyan(" Build complete.\n"));
});