【webpack系列】从零搭建 webpack4+react 脚手架(二)
html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发环境?如何实现开发环境的热更新?
(1)安装html-webpack-plugin:
npm install --save-dev html-webpack-plugin
(2)在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
},
})
]
});
(3)删除index.html中手动引入的script标签
index.html的代码应该是这样的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>从零开始搭建react工程</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
(4)重新执行编译
npm run build
查看dist文件夹,index.html也被加载进来了,并且已经自动加上了script标签。
添加文件hash的方法很简单,只要修改 output.filename 属性即可,这里我们做一个小小的优化,把导出的文件存放在js目录下,并且直接使用name+chunkhash的方式来命名。
filename: "js/[name].[chunkhash:16].js"
其中,name就是模块名称,我们在entry中进行过配置,chunkhash是文件内容的hash,webpack默认采用md5的方式对文件进行hash。16是hash的长度,如果不设置,webpack会设置默认值为20。
现在,你的webpack.prod.conf.js文件看起来应该是这样:
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-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
},
})
]
});
(1)安装clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
(2)修改webpack.prod.conf.js,使用clean-webpack-plugin
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.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 })
]
});
(3)执行试试看
npm run build
编译过程,注意查看控制台输出,你会发现webpack删除了dist目录。
随着我们业务代码的增加,这个包将会越来越大。
你每次发布,这个文件都会被重新下载。你的代码有修改,用户需要重新下载无可厚非。可是,你别忘了这个app.js内还包含了很多不变的代码,比如react,react-dom。我们需要把这些不变的代码分开打包。
在webpack.base.conf.js,我们添加一个入口配置。entry有2个入口。
entry: {
app: './app/index.js',
framework:['react','react-dom'],
},
重新执行npm run build,再看看。
的确,react和react-dom 被编译成framework.js。可是,你会发现,app.js并没有减少,还是96.9KB。因为我们还缺少一步,就是抽离app.js中公共的代码。
webpack3版本是通过配置CommonsChunkPlugin插件来抽离公共的模块。webpack4版本,官方废弃了CommonsChunkPlugin,而是改用配置optimization.splitChunks的方式,更加方便。
在webpack.prod.conf.js增加如下代码:
optimization: {
splitChunks: {
chunks: "all",
minChunks: ,
minSize: ,
cacheGroups: {
framework: {
test: "framework",
name: "framework",
enforce: true
}
}
}
}
cacheGroups对象,定义了需要被抽离的模块,其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来。name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块,虽然他们都叫framework。
重新执行npm run build你看到app.js的体积变小了 才1kb。

注意查看生成的文件的hash,接下去我们随意修改app/index.js的代码。重新执行npm run build编译。看看编译后的结果:

看到了吗,app的hash发生了改变(它不能被浏览器缓存),而framework没有改变(它会被浏览器缓存),这达到了我们预期的结果。
(1)安装uglifyjs-webpack-plugin
npm install --save-dev uglifyjs-webpack-plugin
(2)在webpack.prod.conf.js页面上引入
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
(3)optimization内配置minimizer参数
minimizer: [
new UglifyJSPlugin()
],
你的optimization参数现在应该是这样:
optimization: {
minimizer: [
new UglifyJSPlugin()
],
splitChunks: {
chunks: "all",
minChunks: ,
cacheGroups: {
framework: {
priority: ,
test: "framework",
name: "framework",
enforce: true,
reuseExistingChunk: true
},
vendor: {
priority: ,
test: /node_modules/,
name: "vendor",
enforce: true,
reuseExistingChunk: true
}
}
}
}
(4)重新执行npm run build
npm run build
webpack-dev-server这个模块提供了开发服务的支持,通过在webpack.dev.conf.js文件配置devServer可以方便地整合webpack-dev-server。
(1)安装webpack-dev-server
npm install --save-dev webpack-dev-server
(2)在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: '',
contentBase: path.join(__dirname, '../public'),
compress: true,
historyApiFallback: true,
hot: true,
https: false,
noInfo: true,
open: true,
proxy: {}
}
});
HotModuleReplacementPlugin是webpack热更新的插件,设置devServer.hot为true,并且在plugins中引入HotModuleReplacementPlugin插件即可。
还需要注意的是我们开启了hot,那么导出不能使用chunkhash,需要替换为hash。
(3)在package.json增加一个npm scripts
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
(4)执行dev命令
npm run dev
打开 http://localhost:8080 查看,你可以尝试改动index.js的代码,浏览器自动更新了,说明整合webpack-dev-server成功。
你可能注意到,对于css相关的技术栈,我只字未提,别急,下一节我们会详细针对css相关的技术栈进行整合。
【webpack系列】从零搭建 webpack4+react 脚手架(二)的更多相关文章
- 【webpack系列】从零搭建 webpack4+react 脚手架(一)
搭建一个React工程的方式有很多,官方也有自己的脚手架,如果你和我一样,喜欢刨根究底,从零开始自己一行一行代码创建一个React脚手架项目,那你就来对地方了.本教程是针对React新手,以及对web ...
- 【webpack系列】从零搭建 webpack4+react 脚手架(四)
经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架.如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦 ...
- 【webpack系列】从零搭建 webpack4+react 脚手架(三)
本章节,我们对如何在脚手架中引入CSS,如何压缩CSS,如何使用CSS Modules,如何使用less,如何使用postcss等问题进行展开学习. 1 支持css (1)在app目录,新建一个css ...
- 【webpack系列】从零搭建 webpack4+react 脚手架(五)
本章节,我们一起来探讨以下问题:如何对编译后的文件进行gzip压缩,如何让开发环境的控制台输出更加高逼格,如何更好的对编译后的文件进行bundle分析等. 1 gzip压缩 如果你想节省带宽提高网站速 ...
- 从零搭建Spring Boot脚手架(1):开篇以及技术选型
1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...
- 初探webpack之从零搭建Vue开发环境
初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...
- 从零搭建Spring Boot脚手架(2):增加通用的功能
1. 前言 今天开始搭建我们的kono Spring Boot脚手架,首先会集成Spring MVC并进行定制化以满足日常开发的需要,我们先做一些刚性的需求定制,后续再补充细节.如果你看了本文有什么问 ...
- 从零搭建Spring Boot脚手架(3):集成mybatis
1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文集成了一些基础的功能,比如统一返回体.统一异常处理.快速类型转换.参数校验等常用必备功能,并编写了一些单元测试进行验证,今天 ...
- 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...
随机推荐
- eclipse JVM 性能调优
最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一记录. 一.JVM内存模型及垃圾收集算法 1.根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老 ...
- Security+高分考过经验分享812分
Security +也是无意中从谷安的宣传单知道的,本来就是想从事安全的行业,而且Security +含金量高,是国际认可的认证就想着去考一考试试. 大概从2018.12开始正式准备的,前面时间都是停 ...
- 2018-2019-2 网络对抗技术 20165232 Exp2 后门原理与实践
2018-2019-2 网络对抗技术 20165232 Exp2 后门原理与实践 1. 后门原理与实践实验说明及预备知识 一.实验说明 任务一:使用netcat获取主机操作Shell,cron启动 ( ...
- DEV 控件使用之:TreeList
使用DEV控件也有一段时间了,一直想写点东西.最近又使用到TreeList控件,这个控件对于刚使用的人来说确实不好掌握.我想把自己知道的写下来,让还不熟悉的慢慢学会使用,对于会使用的大家交流下.如果有 ...
- HttpServletRequest基础
一.请求行 二.请求消息头 三.请求正文(重要) 1.获取表单(request)提交的数据 (1)getParameter(name):根据表单name属性的名字,获取name的值 (2)getPar ...
- java基于redis事务的秒杀实现
package com.vian.user.service; import org.junit.Test; import org.springframework.util.CollectionUtil ...
- js 正则表达式,分组,非捕获或 环视的使用
定位一个字符串中,匹配与定位重复字符中的最后一个字符: 例子: <script type="text/javascript"> var str="http:/ ...
- Codeforces Round #541 (Div. 2)题解
不知道该更些什么 随便写点东西吧 https://codeforces.com/contest/1131 ABC 太热了不写了 D 把相等的用并查集缩在一起 如果$ x<y$则从$ x$往$y$ ...
- 多个Fragment在一个activity中通过按钮的展示方法
fragment使用方法 1. 创建主Mainactivity extends AppCompatActivity 2. Oncreate & setContentView 3. 完成XML的 ...
- The Ethereum devp2p and discv4 protocol Part I
描述 本文章分上下两篇 上篇:讲述以太坊devp2p与disc4节点发现协议 下篇:实践篇,实现如何获取以太坊所有节点信息(ip,port,nodeId,client,type,os) 正文 devp ...