react+webpack4搭建前端项目(一)
本文目的实现从零搭建一个react后台管理系统,这是第一章!搭建基本的项目。
本篇主要讲述一步步搭建react
项目雏形(不使用create-react-app
,umi
等),包括配置基本webpack,再到react+webpack
配置整合,到完成项目的启动和打包(不包含react
相关技术栈的使用和webpack
的打包优化)。这些东西我还会在之后更新新的文章来详细讲解react
相关技术栈(全家桶react+react-router+axios+antd+mobx
)的使用以及webpack
打包优化
本文适合人群:react,webpack有一定基础
技术栈
- react框架:
react+react-router+axios+antd+mobx
后边在写项目中会使用,本文不涉及 - 打包构建
webpack4.x
废话不多说,前方高能,正式开始喽
初始化项目
webpack安装(webpack小试牛刀)
-
创建package.json,执行
npm init
一路按enter键就搞定了 -
安装webpack基本包(本文采用webpack4.x,注意了啊,各位同学)
npm install --D webpack webpack-dev-server webpack-cli
webpack4.x
必须安装webapck-cli
,这是一个注意事项
新建src/index.js
,添加代码如下
console.log("hello world")
在package.json
执行脚本添加"build":"webpack"
在终端执行npm run build
,可以看到在根目录生成了dist/main.js的打包文件,这是webpack4.x打包默认找src/index.js打包入口,如下图:
上边已经说明webpack在本项目中可以成功构建打包js文件了,其它用法请查看官方文档!
下边开始正式配置webpack啦~
一步步从最基本的配置出发,到创建不同环境webpack配置文件来区分不同环境,在到详细配置不同环境的webpack;最后配置react的开发和打包环境
webpack的基础配置
1、项目根目录创建build目录,创建webpack.config.js
基本配置
const path = require("path");
function resolve(dir) {
return path.resolve(__dirname, dir)
}
module.exports = {
// 指定构建环境
mode:"development",
// 入口
entry: {
app: "./src/index"
},
// 出口
output: {
path : resolve("../dist"),
filename: "js/[name].[hash].js",
publicPath: "/" // 打包后的资源的访问路径前缀
},
// 模块
module:{
},
// 插件
plugins:[
],
// 开发环境本地启动的服务配置
devServer: {
}
}
上边每一项配置都有注释,有什么不懂的基本配置可以看官方文档
2、编写,配置html模板,实现html模板的打包,安装插件
npm install -D html-webpack-plugin
在根目录创建index.html
模板,代码很简单
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>mydemo</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
3、在webpack.config.js的plugins添加
new HtmlWebpackPlugin({
filename: resolve('./../dist/index.html'), // html模板的生成路径
template: 'index.html',//html模板
inject: true, // true:默认值,script标签位于html文件的 body 底部
hash: true, // 在打包的资源插入html会加上hash
// html 文件进行压缩
minify: {
removeComments: true, //去注释
collapseWhitespace: true, //压缩空格
removeAttributeQuotes: true //去除属性引用
}
})
4、修改package.json
的build命令为指定配置文件构建打包"build": "webpack --config build/webpack.config.js"
,然后再次执行npm run build
,这时候已经可以把html模板和打包后的资源插入到html模板,最后打包进dist目录
抽取webpack配置文件
为了区分开发环境和生产环境,下面我们一步一步抽取wenpack公共配置
分别创建 utils.js ,webpack.base.config.js , webpack.dev.config.js , webpack.prod.config.js
在抽取webpack配置过程中,需要使用webpack-merge插件,安装方式
npm install -D webpack-merge
这个插件是用来合并webpack配置的,可以对不同文件的webpack配置合并成一个完整的webpack配置。具体用法请看下面
utils.js是webpack配置用的工具方法
const path = require("path")
exports.resolve = function (dir) {
return path.resolve(__dirname, dir)
}
webpack.base.config.js 是webpack在不同环境的公共配置
const utils = require("./utils")
module.exports = {
// 入口
entry: {
app: "./src/index"
},
// 出口
output: {
path : utils.resolve("../dist"),
filename: "js/[name].[hash].js",
publicPath: "/" // 打包后的资源的访问路径前缀
},
// 模块
module:{
},
}
webpack.dev.config.js 是项目开发环境的配置
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.config")
const utils = require("./utils")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = webpackMerge(baseWebpackConfig,{
// 指定构建环境
mode:"development",
// 插件
plugins:[
new HtmlWebpackPlugin({
filename: utils.resolve('./../dist/index.html'), // html模板的生成路径
template: 'index.html',//html模板
inject: true, // true:默认值,script标签位于html文件的 body 底部
})
],
// 开发环境本地启动的服务配置
devServer: {
}
});
webpack.prod.config.js 是项目生产环境环境的配置
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.config")
const utils = require("./utils")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = webpackMerge(baseWebpackConfig,{
// 指定构建环境
mode:"production",
// 插件
plugins:[
new HtmlWebpackPlugin({
filename: utils.resolve('./../dist/index.html'), // html模板的生成路径
template: 'index.html',//html模板
inject: true, // true:默认值,script标签位于html文件的 body 底部
hash: true, // 在打包的资源插入html会加上hash
// html 文件进行压缩
minify: {
removeComments: true, //去注释
collapseWhitespace: true, //压缩空格
removeAttributeQuotes: true //去除属性引用
}
})
],
})
在修改package.json
的build命令:
"build": "webpack --config build/webpack.prod.config.js"
然后再次执行npm run build
,一切正常!
配置生产环境webpack.dev.config.js其实上面步骤已经完成,但还比较简单,后边会结合react的打包进行整合
配置开发环境webpack.dev.config.js
开发环境需要我们使用webpack-dev-server插件,上边已经安装过
1、添加package.json命令,用webpack-dev-server启动服务
"dev": "webpack-dev-server",
执行npm run dev
,现在已经可以正常启动一个服务了,默认端口8080,服务的根目录是项目的根目录
但是这种方式没有指定配置文件启动,所以还需改成指定配置文件启动
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.config.js",
在次执行npm run dev
,你会看到配置的资源和html模板已经被webpack构建
这时候浏览器打开http://localhost:8080,看到src/index.js的内容执行了
QQ截图20190810133343.png2、丰富webpack-dev-server配置,在webpack.dev.config.js的devServer属性下添加开发环境启
动服务的配置
// 开发环境本地启动的服务配置
devServer: {
historyApiFallback: true, // 当找不到路径的时候,默认加载index.html文件
hot: true,
contentBase: false, // 告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要
compress: true, // 一切服务都启用gzip 压缩:
port: "8081", // 指定段靠谱
publicPath: "/", // 访问资源加前缀
proxy: {
// 接口请求代理
},
}
执行npm run dev
,启动服务,这时候配置文件已经把服务端口改为8081
,输入http://localhost:8081,修改src/index.js,此时可以看到浏览器会热更新,到此开发环境的配置基本完成,如果需要了解更多请查看文档
引入react框架
安装react
npm install -S react react-dom
修改src/index.js文件,使用react,react-dom
把react
的spa
页面插入到html
模板id
为app
的盒子当中,重新运行项目npm run dev
,不出意外你惊讶的发现报错了。这是此时webpack还不能编译构建react的代码,那么接下来我们进行支持react的打包构建
支持react的打包构建(配置webpack)
我们都知道,要想把react的代码使用webpack编译构建成浏览器可以运行的代码,需要使用babel等工具进行"翻译一下"
1、安装,配置babel(babel7.x)
npm install -D @babel/core @babel/preset-env @babel/preset-react
npm install -D @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2
-
@babel/core babel
babel的核心库 -
@babel/preset-env
把es6,es7语法转换成es5。bebel7以上的版本只用这一个预设包就可以实现语法的转换,已经废弃了preset-stage-0,preset-stage-1,preset-stage-2
等这些包。但是这个包还不能转换es6,es7的一些新特性比如Array.includes()
,这就需要我们使用@babel/plugin-transform-runtime
了 -
@babel/preset-react
把react语法转换为es5 -
@babel/plugin-transform-runtime
支持一些es6,es7的新语法
那么安装完了,我们需要添加babel的配置了,在项目目录创建.babelrc
,配置内容如下
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"@babel/preset-react"
],
"plugins": [
["@babel/plugin-transform-runtime",{
"corejs": 2, // polyfill 需要使用@babel/runtime-corejs2
"useBuildIns":"usage", //按需引入,即使用什么新特性打包什么新特性, 可以减小打包的体积
}]
]
}
上边有两个地方讲解一下,在配置plugin-transform-runtime
时候,需要安装依赖@babel/runtime
,还添加了特殊配置"corejs": 2
,"useBuildIns":"usage"
,为什么添加这些配置呢?
-
"corejs": 2
: @babel/runtime + @babel/plugin-transform-runtime 在 babel7 下只包含 helper function(即 Babel 进行处理时需要的帮助函数), 如果想实现 polyfill , 需要使用@babel/runtime-corejs2。 -
"useBuildIns":"usage"
: 要实现真正的按需引入,即使用什么新特性打包什么新特性,可以使用实验性的 useBuildIns:"usage"。
2、webpack4.x配置编译打包规则
安装loaders
-
babel-loader
使用babel进行编译项目
npm install -D babel-loader
-
style-loader,css-loader
编译css文件
npm install -D style-loader css-loader
-
url-loader file-loader
引入文件路径(图片,字体)
npm install -D url-loader file-loader
-
less-loader
识别less
文件
npm install -D less less-loader
安装完这些包之后,我们需要在webpacl.base.config.js添加打包编译构建规则
在module下添加rules属性
rules:[
{
test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)
exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选)
loader: 'babel-loader',//loader的名称(必须)
},
{
test: /\.css$/,
use:[
{
loader: 'style-loader', // 创建 <style></style>
},
{
loader: 'css-loader', // 转换css
}
]
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader', // 编译 Less -> CSS
},
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // url-loader 包含file-loader,这里不用file-loader, 小于10000B的图片base64的方式引入,大于10000B的图片以路径的方式导入
name: 'static/img/[name].[hash:7].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 小于10000B的图片base64的方式引入,大于10000B的图片以路径的方式导入
name: 'static/fonts/[name].[hash:7].[ext]'
}
}
]
这些配置相比vue框架的配置少了对vue文件的编译构建配置。你会发现在vue项目vue-loader,vue-style-loader,vue-template-compiler
这三个插件是必不可少的,这是用来处理vue文件的包
继续在webpack.base.config.js添加
resolve: {
extensions: ['.js', '.json'], // 解析扩展。(当我们通过路导入文件,找不到改文件时,会尝试加入这些后缀继续寻找文件)
alias: {
'@': path.join(__dirname, '..', "src") // 在项目中使用@符号代替src路径,导入文件路径更方便
}
}
3、编写页面,运行项目,测试打包
新建assets/img目录,把图片放在该目录下
在src
下新建home/index.js
,home/test.css
,home/test.less
home/index.js内容:
import React from 'react'
import "./test.less"
import "./test.css"
import buyImg from "@/assets/img/icon_buy_task.png"
import testImg from "@/assets/img/bg_store.png"
export default class Home extends React.Component {
render(){
return (
<div className="test test2">
<p>hello world</p>
<img src={buyImg} alt="" />
<img src={testImg} alt="" style={{width:360,height:60}}/>
</div>
)
}
}
test.css
.test2 {
font-size: 32px;
}
test.less
.test {
background: rebeccapurple;
}
然后修改src/index.js入口文件
import React from 'react'
import ReactDom from 'react-dom'
import HomePage from "./home"
class App extends React.Component {
render(){
return (
<div style={{color:"#333"}} className="test test2">
<HomePage />
</div>
)
}
}
ReactDom.render(<App/>,document.getElementById("app"))
这时候项目的节本雏形已经形成:
QQ截图20190812122733.png
然后我们运行和打包项目
先执行npm run dev
,服务正常启动,浏览器打开http://localhost:8081
页面效果:
最后打包执行npm run build
,打包成功
此时,比较大的图片和js的bundle都已经正常打包,那么我们怎么测试打包的代码正常呢?这里我推荐一个插件(不用把静态包部署到nginx服务器就可以运行)http-server
npm install -g http-server
全局安装http-server包,安装成功之后,cd dist
目录,执行http-server
命令
这时候启动了一个服务,默认开启8080端口
如下图:
QQ截图20190812123523.png
这时候打开浏览器,输入http://localhost:8081,发现页面正常访问!
就这样一个基本的项目雏形有了!
下一篇: react技术栈的使用,敬请期待~