react 引用本地js_从零配置webpack 4+react脚手架(二)
前言:
你可能也注意到了,html文件中的关于js的引用是我们手动写的,那假如我们改了输出路径或打包编译之后的文件名,那我们岂不是还要手动去修改html文件中的引用?我们怎么做到,像create-react-app中那样一旦你修改了某个文件内容,页面会自己刷新?我们来一步一步实现它们,当然,这一小节不仅仅只是为了完成这两点。
上一节:从零配置webpack 4+react脚手架(一)
自动编译html并引入js文件
public的index.html应该自动编译到dist目录,并且所有的js引用是自动添加的。你可以使用html-webpack-plugin插件来处理这个优化。
安装HtmlWebpackPlugin
在控制台执行以下代码:
npm install --save-dev html-webpack-plugin
在webpack.prod.config.js中配置plugins属性
const merge = require('webpack-merge');
const common = require('./webpack.common.config.js');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = merge(common, {mode: 'production',plugins: [new HtmlWebpackPlugin({filename: 'index.html',// 这里有小伙伴可能会疑惑为什么不是 '../public/index.html'// 我的理解是无论与要用的template是不是在一个目录,都是从根路径开始查找template: 'public/index.html',inject: 'body',minify: {removeComments: true,collapseWhitespace: true,},})]
});
- filename:打包之后的html文件名字
- template:以我们自己定义的html为模板生成,不然我们还要到打包之后的html文件中写
- inject:在body最底部引入js文件,如果是head,就是在head中引入js
- minify:压缩html文件,更多配置点我
- removeComments:去除注释
- collapseWhitespace:去除空格
更多配置请点击官方README
删除index.html中手动引入的script标签
<!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>从零配置webpack4+react脚手架</title>
</head>
<body><div id="root"></div>
</body>
</html>
现在我们再来打包试试,看看dist中是不是多出了html文件,并且自动引入了script,用浏览器打开它试试看是不是能正确输出内容了!
给打包出的js文件换个不确定名字
这个操作是为了防止因为浏览器缓存带来的业务代码更新,而页面却没变化的问题,你想想看,假如客户端请求js文件的时候发现名字是一样的,那么它很有可能不发新的数据包,而直接用之前缓存的文件,当然,这和缓存策略有关。
那我们怎么给导出文件的安排一个不确定的名字呢?很简单,[hash]或[chunkhash]
修改webpck.prod.config.js
:
const merge = require('webpack-merge');
const common = require('./webpack.common.config.js');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = merge(common, {mode: 'production',output: {filename: 'js/[name].[chunkhash:8].bundle.js',},plugins: [new HtmlWebpackPlugin({filename: 'index.html',template: 'public/index.html',inject: 'body',minify: {removeComments: true,collapseWhitespace: true,},})]
});
其中,name
就是模块名称,我们在entry中进行过配置,在这里重新设置会代替之前common中的设置,chunkhash
是文件内容的hash,webpack默认采用md5的方式对文件进行hash。8是hash的长度,如果不设置,webpack会设置默认值为20。
现在你重新打包,去看看生成的js文件的名字~
打包编译前清理dist目录
在上面的修改后,因为js文件名字不同,你之后再打包,会把之前打包之后的js文件也留下,我们只想要最新打包编译的文件,就需要先清除dist目录,再重新生成。
安装clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
这个插件不被官方文档所收录,可以去github查看它的配置文档
使用clean-webpack-plugin
修改webpck.prod.config.js
:
const merge = require('webpack-merge');
const common = require('./webpack.common.config.js');const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = merge(common, {mode: 'production',output: {filename: 'js/[name].[chunkhash:8].bundle.js',},plugins: [new HtmlWebpackPlugin({filename: 'index.html',template: 'public/index.html',inject: 'body',minify: {removeComments: true,collapseWhitespace: true,},}),new CleanWebpackPlugin()]
});
这里需要注意:之前引入CleanWebpackPlugin的写法是const CleanWebpackPlugin = require('clean-webpack-plugin');
而且在下面new的时候需要传入参数,dist文件路径。但是现在必须这样引入:const {CleanWebpackPlugin} = require('clean-webpack-plugin');
而且,不用再写路径参数
现在再来执行看看,是不是只有一个js文件了!~
代码分割
我们先看下,我们之前打包编译的时候,控制台的信息:
我们看到,这个打包之后的bundle.js文件大小为129kb,随着业务代码越来越多,这个包会变得越来越大,你每次修改了代码并发布,用户都需要重新下载这个包,但是想想看,我们修改的代码只是整个代码的一小部分,还有许多其他不变的代码,例如 react
和 react-dom
,那我们把这部分不变的代码单独打包。
修改 webpack.common.config.js
,增加一个入口:
entry: {index: './src/index.js',framework: ['react','react-dom'],},
重新打包,发现react和react-dom 被编译成framework.js,但是我们的index.bundle.js还是129kb,没有变过。
这是因为我们还没有抽离index.js中的公共代码。
webpack3版本是通过配置CommonsChunkPlugin插件来抽离公共的模块。webpack4版本,官方废弃了CommonsChunkPlugin,而是改用配置optimization.splitChunks的方式,更加方便。
添加代码至 webpack.prod.config.js
:
module.exports = {//...optimization: {splitChunks: {chunks: 'all',minSize: 30000,maxSize: 0,minChunks: 1,cacheGroups: {framework: {test: "framework",name: "framework",enforce: true},vendors: {priority: -10,test: /node_modules/,name: "vendor",enforce: true,},}}},//...
};
cacheGroups对象,定义了需要被抽离的模块,其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来。name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块,虽然他们都叫framework。
vendors这个缓存组,它的test设置为 /node_modules/ 表示只筛选从node_modules文件夹下引入的模块,所以所有第三方模块才会被拆分出来。
重新打包,我们发现index.bundle.js文件大小只有:1.69kb
我们随意修改一下app.js中的内容,比如
import React from 'react';function App() {return (<div className="App"><h1>I am changed</h1></div>);
}export default App;
再打包一次,你会发现index.bundle.js(不被缓存)的hash值变了,但是freamework.bundle.js(能被缓存)的hash值没变,成了成了!!
压缩JS文件
我们需要把打包生成的js文件尽可能压缩,以便减少文件体积,更快地被用户加载。
我们需要一个插件: uglifyjs-webpack-plugin
来做这份工作
安装uglifyjs-webpack-plugin
在控制台执行以下代码:
npm install uglifyjs-webpack-plugin --save-dev
引入uglifyjs-webpack-plugin
增加如下代码至 webpack.prod.config.js
:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
optimization内配置minimizer参数
minimizer: [new UglifyJsPlugin(),//...
],
现在optimization参数应该是现在这样:
optimization: {minimizer: [new UglifyJsPlugin()],splitChunks: {chunks: 'all',minSize: 30000,maxSize: 0,minChunks: 1,cacheGroups: {framework: {priority: 100,test: "framework",name: "framework",enforce: true},vendors: {priority: -10,test: /node_modules/,name: "vendor",enforce: true,},}}},
重新打包编译看看~我们的index.bundle.js减少了0.1kb,当然,随着业务代码越来越多,这部分差距会渐渐变大。
自动编译打包
我们每次修改代码,查看结果都要经历以此 npm run build
,大大降低了开发效率,这难以忍受!
webpack给我们提供了devServer开发环境,支持热更新,相当舒服。
安装webpack-dev-server
在控制台执行以下代码:
npm install webpack-dev-server --save-dev
增加代码至 webpack.dev.config.js
:
是不是都快忘记这个之前创建的配置文件了?没关系,反正也没代码,它是专门用来配置我们开发环境的
const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.config.js');const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = merge(common, {mode: 'development',output: {filename: 'js/[name].[hash:8].bundle.js',},devServer: {contentBase: path.resolve(__dirname, '../dist'),open: true,port: 9000,compress: true,hot: true},plugins: [new HtmlWebpackPlugin({template: 'public/index.html',inject: 'body',hash: false}),new webpack.HotModuleReplacementPlugin()]
});
HotModuleReplacementPlugin
是webpack热更新的插件,设置devServer.hot
为true,并且在plugins中引入HotModuleReplacementPlugin插件即可。
还需要注意的是我们开启了hot,那么导出不能使用chunkhash,需要替换为hash。
修改我们的package.json
像之前build的时候,我们是通过配置package.json做到的,现在我们同样加入以下代码来模拟:
"scripts": {"test": "echo "Error: no test specified" && exit 1","build": "webpack --config ./config/webpack.prod.config.js",
+ "start": "webpack-dev-server --inline --config ./config/webpack.dev.config.js"},
接下来,在控制台执行
npm run start
是不是自动开了一个端口为9000的网页,上面是我们写的页面内容,这和我们的配置都是一一对应的。
现在你随意修改app.js中的代码,再回到页面看下是不是也跟着变了,那我们就整合webpack-dev-server成功!
下面一小节我们会配置css相关的属性,加油!
这是我的github/blog,欢迎star,会陆续推出更多学习文章。
react 引用本地js_从零配置webpack 4+react脚手架(二)相关推荐
- react 文件 md5_从零配置webpack 4+react脚手架(二)
前言: 你可能也注意到了,html文件中的关于js的引用是我们手动写的,那假如我们改了输出路径或打包编译之后的文件名,那我们岂不是还要手动去修改html文件中的引用?我们怎么做到,像create-re ...
- 从零搭建webpack的react开发/生产环境
一.初始化项目 在命令行中敲入如下命令: mkdir Webpack-react && cd Webpack-react && npm init -y 然后你就可以在你 ...
- react打包后图片丢失_使用 webpack 搭建 React 项目
简评:相信很多开发者在入门 react 的时候都是使用 create-react-app 或 react-slingshot 这些脚手架来快速创建应用,当有特殊需求,需要修改 eject 出来的 we ...
- 从零配置webpack(react+less+typescript+mobx)
本文目标 从零搭建出一套支持react+less+typescript+mobx的webpack配置 最简化webpack配置 首页要初始化yarn和安装webpack的依赖 yarn init -y ...
- react 引用本地js_react组件中如何引入一个外部的js文件?
推荐两种引入的方法,当然也可以自己编写一个JS类(ES6语法)实现动态插入JS到页面,然后在React项目引入. 第一种:使用插件 react-load-script,如果没有安装可以使用 yarn ...
- webpack搭建php服务器,webpack搭建react开发环境步骤详解
这次给大家带来webpack搭建react开发环境步骤详解,webpack搭建react开发环境的注意事项有哪些,下面就是实战案例,一起来看一下.mkdir react-redux && ...
- React+TS学习和使用(三):React Redux和项目的路由配置
开启学习react+ts,本篇主要是学习使用React Redux和项目的路由配置 一.React Redux 需求:使用TS+React Redux实现一个累加. A. 安装 $ yarn add ...
- react打包后图片丢失_如何快速构建React组件库
俗话说:"麻雀虽小,五脏俱全",搭建一个组件库,知之非难,行之不易,涉及到的技术方方面面,犹如海面风平浪静,实则暗礁险滩,处处惊险〜 目前团队内已经有较为成熟的 Vue 技术栈的 ...
- webpack打包压缩混淆_细说webpack系列 3. webpack-cli 零配置打包
大家好!我是萝卜,webpack 4 带来了大量的更新,其中一个就是webpack 4 默认不需要配置文件,下面就带大家体验一下! 初始化项目 首先创建项目,创建一个名为webpack的文件夹,进入文 ...
最新文章
- ehcache config xml file
- Oracle中group by用法
- Linux下C/C++开发工具注意事项
- Windows Live Writer 的昨日荣光
- 一所传闻要被“降级”的211高校,让这位网红教授“救活了”
- 前端学习(3115):react-hello-初始化state
- Luogu 4514 上帝造题的七分钟
- Pandas 文本数据方法 count( )
- 从服务器上下载下来的代码,部署到本地时,Url自动带www前缀
- 简单聊聊网页的资源加载优化
- ORACLE建表语句转化为MySQL建表语句
- Ubuntu20.04 安装星火商店安装Windows等应用
- 韩立刚老师 《计算机网络》视频课程目录
- GIS空间服务赋能邵阳不动产登记可视化办理
- Navicat 设置自动插入时间触发器
- 捷达vs7测试_抢先测试捷达VS7!你期待吗
- kettle启动 carte
- 华清远见-重庆中心-JAVA基础阶段技术总结/知识点梳理/个人总结/关于JAVA技术的解析(看法)/面试题解析
- vue 项目实战 递归
- pymssql 安装和使用
热门文章
- 检查文件上传完成_“我的数据上传NCBI又报错了...” “攻略拿去!”
- [原创]同一页面无法多次使用XmlHttp发起Ajax请求的真实原因
- 高级C语言教程-C语言函数setjmp()函数
- python的set结构
- java中static{}语句块详解
- 问题解决:无法获得锁 /var/lib/dpkg/lock
- Mysql流程控制结构
- springboot学习笔记(十)
- 图像和流媒体 -- 详解YUV数据格式
- 数据结构:平衡二叉树概念、旋转