本文目的实现从零搭建一个 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 打包入口, 如下图:
QQ 截图 20190810105541.PNG
QQ 截图 20190810105621.PNG
上边已经说明 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 目录
QQ 截图 20190810113953.PNG
抽取 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, 服务的根目录是项目的根目录
QQ 截图 20190810161241.PNG
但是这种方式没有指定配置文件启动, 所以还需改成指定配置文件启动
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.config.js",
在次执行 NPM run dev, 你会看到配置的资源和 HTML 模板已经被 webpack 构建
QQ 截图 20190810162214.PNG
这时候浏览器打开 http://localhost:8080, 看到 src/index.JS 的内容执行了
QQ 截图 20190810133343.PNG
2, 丰富 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, 此时可以看到浏览器会热更新, 到此开发环境的配置基本完成, 如果需要了解更多请查看文档
webpack-dev-server 详细配置
引入 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 babelbabel 的核心库
@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
页面效果:
QQ 截图 20190812123014.PNG
最后打包执行 NPM run build, 打包成功
QQ 截图 20190812123144.PNG
此时, 比较大的图片和 JS 的 bundle 都已经正常打包, 那么我们怎么测试打包的代码正常呢? 这里我推荐一个插件(不用把静态包部署到 nginx 服务器就可以运行)http-server
NPM install -g http-server
全局安装 http-server 包, 安装成功之后, cd dist 目录, 执行 http-server 命令
这时候启动了一个服务, 默认开启 8080 端口
如下图:
QQ 截图 20190812123523.PNG
这时候打开浏览器, 输入 http://localhost:8081, 发现页面正常访问!
就这样一个基本的项目雏形有了!
来源: http://www.jianshu.com/p/04e436cf75ba