参考资源:
https://www.jianshu.com/p/8f49aaa6169e
https://www.jianshu.com/p/bcad129a1c69
初始化文件npm install
全局安装webpack npm install webpack -g
添加src文件夹,创建index.js文件,下面对index.js文件内容进行打包
在webpack.config.js下对webpack打包出入路径进行设置
const path = require('path');//路径解析
module.exports = {
entry: './src/index.js', // 打包入口文件
mode: 'development',
output: {
path: path.resolve(__dirname, 'build'), // 打包路径到build文件夹下
filename: 'bundle.js', // 生成打包文件名
},
};
package.json中script下添加 "build": "webpack --config webpack.config.js"//通过--config进行文件配置,后续可通过npm run build进行打包
package.json中script下添加"dev": "webpack-dev-server"实现npm run dev后在浏览器下起服务查看的效果,默认url是 http://localhost:8080/,此时有一个问题就是输入对应路径后打开的是对应根路径,而不是index页面
为了让页面打开就可以显示html文件入口,需要结合webpack-dev-server配置devServer
devServer: {
port: 3000,
contentBase: './bundle',
hot: true,
},
src下添加index.html,引入html-webpack-plugin插件
先安装 npm install html-webpack-plugin,并进行如下配置
const path = require('path');
const HtmlPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js', // 打包入口文件
mode: 'development',
output: {
path: path.resolve(__dirname, 'build'), // 打包路径到build文件夹下
filename: 'bundle.js', // 生成打包文件名
},
plugins: [
new HtmlPlugin({ // 生成html文件入口
template: './public/index.html', // 源模板文件,打包后生成的html文件是以'./public/index.html'文件作为主入口并进行打包
filename: 'index.html', // 打包后生成的html文件名
minify: {
collapseWhitespace: true, // 折叠html文件中的空行
removeAttributeQuotes: true, // 删除双引号
removeComments: true, // 去掉注释
},
}),
],
};
build后再dev页面可以看见刚进入打开的是对应index.html文件内容
对于内部css文件需要使用css-loader对@import外联样式和url()引入进行css转换,同时还需要配置style-loader将css插入到dom中
并在webpack.config.js下进行loader配置,在此过程中也可能会用到css相关预处理器比如less、sass等,需要引入相应loader进行css转换;也可以添加postcss-loader配合autoprefixer给css样式添加前缀实现兼容处理,需要注意的是要需要新建一个postCss.config.js文件将autoprefixer插件引入
module: {
rules: [
{
test: /\.css$/, // 匹配.css文件
use: ['style-loader', 'css-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
{
test: /\.less$/, // 匹配.css文件
use: ['style-loader', 'css-loader', 'less-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
],
},
//postCss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
],
};
此时可能遇到一个问题:没有添加前缀,解决办法:在package.json文件中添加
"browserslist": [
"iOS >= 6",
"Android >= 4",
"IE >= 9"
],
如果想把自定义样式放到head中 :需要在style-loader初设置insert:'top'
使用mini-css-extract-plugin将css文件提取为独立的css文件(将style-loader替换成MiniCssPlugin.loader),同时添加optimize-css-assets-webpack-plugin插件压缩css文件
const path = require('path');
const HtmlPlugin = require('html-webpack-plugin');
const MiniCssPlugin = require('mini-css-extract-plugin');
const OptimizecssPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
entry: './src/index.js', // 打包入口文件
mode: 'development',
output: {
path: path.resolve(__dirname, 'build'), // 打包路径到build文件夹下
filename: 'bundle.js', // 生成打包文件名
},
plugins: [
new HtmlPlugin({ // 生成html文件入口
template: './public/index.html', // 源模板文件,打包后生成的html文件是以'./public/index.html'文件作为主入口并进行打包
filename: 'index.html', // 打包后生成的html文件名
minify: {
collapseWhitespace: true, // 折叠html文件中的空行
removeAttributeQuotes: true, // 删除双引号
removeComments: true, // 去掉注释
},
}),
new MiniCssPlugin({
filename: 'main.css',
}),
new OptimizecssPlugin({}),
],
module: {
rules: [
{
test: /\.js$/, // 匹配.css文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
include: path.resolve(__dirname, 'src'),
},
},
},
{
test: /\.css$/, // 匹配.css文件
use: [MiniCssPlugin.loader, 'css-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
{
test: /\.less$/, // 匹配.css文件
use: [MiniCssPlugin.loader,'css-loader', 'less-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
],
},
};
安装react react-dom 进行react脚手架搭建npm install react react-dom --save-dev
修改入口文件index.js写成组件形式,高级语言无法被浏览器识别,需要引入babel-loader进行转译成es5,同时针对es5以及jsx语法还需要使用 @babel/preset-react和@babel/preset-react
{
test: /\.js$/, // 匹配.css文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
include: path.resolve(__dirname, 'src'),
},
},
},
修改index.js中文件,同时在index.html下添加js(一般是id='root')插入的根节点
///index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<Title>Document</Title>
<style>
body {
background: pink;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
</html>
///index.js
import React, { Component } from 'react';
import ReactDom from 'react-dom';
const a = require('./a');
require('./body.css');
require('./a.less');
class App extends Component {
render() {
return <h1> Hello, world! </h1>;
}
}
ReactDom.render(
<App />,
document.getElementById('root'),
);
图片需要使用url-loader或file-loader进行转换,对于不超过limit限制大小的图片使用url-loader可以将图片转为base64形式减少http请求,超过限制大小的自动使用file-loader来进行转换,url-loader也可以用来转换字体
{
test: [/\.jpe?g$/, /\.gif$/, /.\png$/],
use: {
loader: 'url-loader',
options: {
limit: 10000, // 10000B 对照1024差不多9点几kb
name: 'image/[name]_[hash].[ext]',
},
},
},
热更新主要基于webpack-dev-derver实现,webpack-dev-derver会自动刷新页面
实现热更新第一步需要在devServer中开启热更新开关hot:true
之后可以添加HotModuleReplacementPlugin插件或是在package的"dev"内添加 --hot(需要注意的是,两者任选一,否则会报错: Maximum call stack size exceeded)
但是我们想要的效果是不刷新页面的同时替换旧模块,简单配置一个hot随意更改一下dom会发现页面还是自己自动刷新了,这个时候需要结合module.hot,对于不需要自动刷新部分使用module.hot.accept()
if (module.hot) {
module.hot.accept(() => {
ReactDom.render(
<App />,
document.getElementById('root'),
);
});
}
ReactDom.render(
<App />,
document.getElementById('root'),
);
平时我们npm run dev后就会自动打开,这个可以在package.json下添加--open
"dev": "webpack-dev-server --hot --open"
在更新css样式的时候发现修改样式并没有同步更新,此时可以引入css-hot-loader实时更新css样式
{
test: /\.css$/, // 匹配.css文件
use: ['css-hot-loader',
MiniCssPlugin.loader, 'css-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
{
test: /\.less$/, // 匹配.css文件
use: ['css-hot-loader', MiniCssPlugin.loader, 'css-loader', 'less-loader', 'postcss-loader'], // 从右向左进行顺序转换
},
在写箭头函数时需要在babel-loader下添加@babel/plugin-proposal-class-properties编译类
{
test: /\.js$/, // 匹配.js文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
include: path.resolve(__dirname, 'src'),
plugins: [
'@babel/plugin-proposal-class-properties',
],
},
},
},