koa2 + react + node后台+热更新

▼魔方 西西 提交于 2019-12-09 21:57:21

技术栈

  • react+webpack 支持前台编写。node+mysql做后台维护
  • 使用ts,包括了tsc,bable7,antd
  • 使用mysql,koa-route 做路由

react+webpack配置

由于使用bable7 ,所以直接使用.babelrc 解析react、ts、es6高级语法
.babelrc相关配置如下,此文件位于项目根目录下。

//.babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false
      }
    ],
    ["@babel/preset-react"],
    ["@babel/preset-typescript"]
  ],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd"
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ],
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    "@babel/plugin-syntax-dynamic-import"
  ]
}

同样需要配置tsconfig.json,此文件位于项目根目录下。内容如下

{
    "compilerOptions": {
        "outDir": "./dist",
        "module": "esnext",
        "target": "es5",
        "lib": [
            "es6",
            "dom"
        ],
        "sourceMap": true,
        "allowJs": true,
        "jsx": "react",
        "moduleResolution": "node",
        "forceConsistentCasingInFileNames": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": true,
        "allowSyntheticDefaultImports": true,
        "skipLibCheck": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "allowUnreachableCode": true,
        "noImplicitAny": false
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

这是基础配置,接下来是配置webpack.config.js,此文件位于项目根目录下
区分了开发和线上环境

if (process.env.NODE_ENV === "development") {
  module.exports = require("./config/webpackconfig");
} else {
  module.exports = require("./config/webpackconfig");
}

根据webpack.config.js中文件的路径,新建生产和线上的webpack 配置,有几个小知识点,
1、使用了happypack ,直接打包了babel-loader
2.1、output.path是硬盘文件路径
2.2、output.publicPath配置的是打包文件输出的访问路径
3、const MiniCssExtractPlugin = require(“mini-css-extract-plugin”);这个可以将.tsx中引入的.less 文件拆分出来
4、const HtmlWebpackPlugin = require(“html-webpack-plugin”);可以根据你设置的路径在dist中生成.html模版,并且将3中拆分出来的less 引入到dist/index.html中
5、new webpack.optimize.OccurrenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(),
这三个是是用于koa-webpack-dev-middleware热更新的,随后配置后端的时候,会再提到
下面是webpack 代码

const path = require("path");
const webpack = require("webpack"); // 加载webpack 中的模块
const HappyPack = require("happypack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const os = require("os");
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const nodeEnv = "development";
module.exports = {
  mode: process.env.NODE_ENV,

  entry: {
    index: [
      "@babel/polyfill",
      "webpack-hot-middleware/client?noInfo=true",
      "./src/index.tsx"
    ]
  },
  output: {
    path: path.join(__dirname, "../dist"),
    publicPath: "/dist/",
    filename: "js/[name].js",
    chunkFilename: "js/[name].chunk.js"
  },

  module: {
    rules: [
      {
        test: /\.(js?|ts?|jsx?|tsx?)$/,
        exclude: /node_modules/,
        use: ["happypack/loader?id=babel"]
      },
      {
        test: /\.(c|le)ss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              hmr: process.env.NODE_ENV === "development"
              //reloadAll: true,
            }
          },
          "css-loader",
          "postcss-loader",
          "less-loader"
        ]
      }
    ]
  },

  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.DefinePlugin({
      "process.env": {
        NODE_ENV: JSON.stringify(nodeEnv),
        NODE_LOCATION: JSON.stringify(process.env.NODE_ENV)
      }
    }),
    new HappyPack({
      id: "babel",
      loaders: [
        {
          loader: "babel-loader"
        }
      ],
      threadPool: happyThreadPool
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
      chunkFilename: "css/[name].css",
      ignoreOrder: false
    }),
    new HtmlWebpackPlugin({
      filename: "index.html",
      template: "index.html",
      inject: true
    })
  ],

  resolve: {
    //有些不同的模块会区分不同的代码这里决定使用哪份代码,例如es6 and es5
    mainFiles: ["index.web", "index"],
    modules: [path.resolve(__dirname, "src"), "node_modules"],
    // 添加让webpack 解析的后缀 例如 ./entry ,优先匹配entry.ts,entry.tsx,最后是entry.js
    extensions: [".ts", ".tsx", ".js", ".json", ".less", ".css"]
  },
  performance: {
    hints: false
  }
};

总的来说,react+webpack 前半部分基本上就是这样了
package.json 启动脚本是这样的

   "start": "cross-env NODE_ENV=development  nodemon --watch 'server_koa.js' -e ts,tsx --exec 'ts-node' ./server_koa.js ",

koa_server.js,在后半部分详细介绍,启动http 服务,做接口请求。
nodemon 检测server_koa.js,支持检测路径’server/**/*’,当使用ts 编写后台时,可以直接重新编译,然后重启ts-node’ ./server_koa.js 服务

======================手动分割线=

现在是重中之重koa2+node +koaroute路由做接口
koa2 是轻量级的服务器接口

  • koa2 中没有像express中可以直接使用use,或者get 拦截处理路由,需要使用const Router = require(“koa-router”);做路由分发,也可以自己做这一步,不过麻烦
  • koa2 中同样没有静态文件分发,需要使用const send = require(“koa-send”);进行react打包的js 和less 进行模版发送,就是webpack 中从.tsx中抽离出来的js 和less 。也有资源说可以使用koa-static,但是,但是我这里加在不出来js和less,报错404.所以最后问同事才了解到koa-send。koa-static是继承实现koa-send,所以问题不大。
    下面就是这一块代码,/dist/是webpack 中 output.publicpath 路径,检测系统访问的时候分发文件资源,
    /test/是项目文件,就是react route 的路径,也就是浏览器地址栏的路径
    这里配置中间件的格式,返回我们配置的模版,所有的访问路径都会经过这个中间件
router.get("/dist/*", async (ctx, next) => {
  await send(ctx, ctx.path);
});
// app.use(static(__dirname + "/dist/", { extensions: ["html"] }));

router.get("/test/*", async (ctx, next) => {
  ctx.type = "html";
  ctx.body = fs.createReadStream("dist/index.html");
  await next();
});

nodemon 是检测server,也就是用ts 写的node后台。现在使用

const  webpackDevMiddleware = require("koa-webpack-dev-middleware");
const webpackHotMiddleware = require("koa-webpack-hot-middleware");

const wdm = webpackDevMiddleware(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
});
app.use(wdm);
app.use(webpackHotMiddleware(compiler));

这两块内容来对.tsx 文件进行热更新。webpackDevMiddleware这个板块中的必须注明 publicPath: config.output.publicPath这个路径,否则不能进行文件热更新,因为找不到更改的文件对应的板块,出现的问题就是hot-update.json找不到,这个链接中注明了publicPath必须写明的原因。
还有就是config/webpackconfig.js 中使用的那三个插件

new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),

注意npm 官网上的这三个插件名称不正确,会直接在webpack 编译中直接报错,拿着报错信息自行百度一下就会有结果。
明天继续…

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!