Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

已有的react vite项目怎么改造呢 #60

Open
qiang-chen opened this issue Mar 30, 2023 · 5 comments
Open

已有的react vite项目怎么改造呢 #60

qiang-chen opened this issue Mar 30, 2023 · 5 comments
Labels
documentation Improvements or additions to documentation

Comments

@qiang-chen
Copy link

No description provided.

@fantasticsoul
Copy link
Collaborator

已有vue项目参考这个示例:
https://github.com/hel-eco/vue-admin-template-with-hel

@fantasticsoul
Copy link
Collaborator

react 参考这个

已有react项目接入hel

安装工具包

安装 hel-dev-utils

npm i hel-dev-utils

生成子应用描述对象

以执行弹射后的create-react-app项目模板为例,建议在config目录下创建一个subApp.js文件,copy如下内容

const helDevUtils = require('hel-dev-utils');
const pkg = require('../package.json');

const subApp = helDevUtils.createReactSubApp(pkg);

// 若是私服部署,可设定 homePage
// const subApp = helDevUtils.createReactSubApp(pkg, {homePage:'https://xxx.com/yy'});

module.exports = subApp;

替换publicUrlOrPath和buildPath

config目录下找到paths文件,替换掉里面的publicUrlOrPathbuildPath定义值

const subApp = require('./subApp');

const publicUrlOrPath = subApp.getPublicPathOrUrl();
const buildPath = subApp.distDir;

替换jsonpFunction

替换config/webpack.config.js文件里output.jsonpFunction(或output.chunkLoadingGlobal)对象下的内容(有则替换,无则新增)

  • webpack 4
{
  // 其他属性略...
  jsonpFunction: subApp.jsonpFnName
}
  • webpack 5
    webpack 5 已将jsonpFunction替换为chunkLoadingGlobal,所以替换或新增的属性和 webpack 4 有差异
{
  // 其他属性略...
  chunkLoadingGlobal: subApp.jsonpFnName, 
}

设置react为externals

推荐设置react为externals,避免react参与打包,同时也方便后续hel-micro-reactSDK使用其他的远程react模块

替换config/webpack.config.js文件里module.exports返回对象的externals值(有则合并,无则新增)

  • 已有自己定义的externals
const subApp = require('./subApp');

module.exports = function (webpackEnv) {
  return {
    // 其他属性略...
    externals: {...yourExternals, ...subApp.externals},
  };
}
  • 无externals
const subApp = require('./subApp');

module.exports = function (webpackEnv) {
  return {
    // 其他属性略...
    externals: subApp.externals,
  };
}

public/index.html里引入cdn react运行时

  • ver 18
<script src="https://tnfe.gtimg.com/hel-runtime/level1/18.1.0-react.dev.js"></script>
  • ver 17
<script src="https://tnfe.gtimg.com/hel-runtime/level1/17.0.2-react.dev.js"></script>
  • ver 16
<script src="https://tnfe.gtimg.com/hel-runtime/level1/16.14.0-react.dev.js"></script>

注:.dev 后缀仅为了本地调试时方便查看详细错误,部署时插件会自动替换为 production 版本,其他版本可联系 fantasticsoul 帮忙发布,此处可根据实际情况可以去掉.dev后缀

暴露共享模块

当前项目有共享给其他项目使用的模块时,可接入此步骤

安装工具包

执行以下npm命令,安装相关包体

npm i hel-lib-proxy
npm i [email protected] rollup@2 rollup-plugin-typescript rollup-plugin-terser shx replace-absolute-path -D

下沉入口文件

将原来的 src/index.js 内容复制到 src/loadApp.js 里,类似此文件,原入口文件index.js内容改动稍后步骤会提到

新增模块组名描述文件

package.json里的appGroupName写上模块组名

新增 src/configs/subApp.ts(如是js工程,此处创建为subApp.js),内容如下,确保LIB_NAMEpackage.json里的appGroupName保持一致

/*
|--------------------------------------------------------------------------
|
| 对应 package.json appGroupName
|
|--------------------------------------------------------------------------
*/
export const LIB_NAME = 'remote-react-comps-tpl';

新增模块暴露目录

新增 src/entrance 目录作为统一暴露模块的出口目录(可参考此文件

目录下新建两个文件libProperties.ts(如是js工程,此处创建为libProperties.js)和libTypes.ts(注意此文件一定是ts文件)

libProperties.ts用于暴露共享模块

// 导出模块可按项目实际情况调整,这里仅做示例
import * as comps from 'components';

export default comps;

libTypes.ts用于导出共享模块类型,并作为rollup打包入口,方便有静态导入和类型提示需求的用户使用npm包来完成此目的,内容如下

import libProperties from './libProperties';
import { exposeLib } from 'hel-lib-proxy';
import { LIB_NAME } from 'configs/subApp';

export type Lib = typeof libProperties;

export const lib = exposeLib<Lib>(LIB_NAME);

/** 如想使用方可在import语句里直接解构出具体的模块,可写为
可参考:https://github.com/hel-eco/hel-tdesign-react/blob/main/src/entrance/libTypes.ts

export cont XX = lib.XX;
export cont YY = lib.YY;

*/

export default lib;

改造入口文件

改造入口文件,做分流控制(可参考此文件

// import { preFetchLib } from 'hel-micro';
import { libReady, isSubApp } from 'hel-lib-proxy';
import { LIB_NAME } from './configs/subApp';

async function main() {
  // 如有其他包依赖,且需要在逻辑里静态导入,可在此处执行预抓取
  // await helMicro.preFetchLib('other-lib');
  const libProperties = await import('./entrance/libProperties');
  // 表示模块已准备就绪,注意此处传递的是 default
  libReady(LIB_NAME, libProperties.default);

  // 非子应用时(即不是被别的模块触发载入的情况),自己挂载渲染节点,方便本地调试
  if (!isSubApp()) {
    await import('./loadApp');
  }
}
main().catch(console.error);
// avoid isolatedModules warning
export default 'Hel Module Index file';

接入npm构建相关辅助脚本

项目根目录下新建scripts目录,新增以下脚本meta.jscheck.jsreplaceToRelativePath.js(可参考此处

meta.js用于辅助私有部署时提取hel-meta.json数据,内容如下:

/*
* 生成 hel-meta.json
*/
const path = require('path');
const process = require('process');
const helDevUtils = require('hel-dev-utils');
const packageJson = require('../package.json');
const subApp = require('../config/subApp');

helDevUtils.extractHelMetaJson({
  appHomePage: subApp.getPublicPathOrUrl(),
  buildDirFullPath: path.join(__dirname, '../hel_dist'),
  packageJson,
  platform: subApp.platform,
}).catch((err) => {
  console.error(err);
  process.exit(-1);
});

check.js用于校验组名是否一致,内容如下:

const path = require('path');
const helDevUtils = require('hel-dev-utils');
const pkg = require('../package.json');
const fileFullPath = path.join(__dirname, '../src/configs/subApp');
helDevUtils.check(pkg, { fileFullPath, checkEnv: process.env.CHECK_ENV !== '0' });

replaceToRelativePath.js用于将整个项目的绝对路径替换为相对路径,辅助rollup打包,内容如下

const path = require('path');
const replacePath = require('replace-absolute-path');

(async function () {
  const srcDir = process.env.BUNDLE === 'true' ? path.resolve(__dirname, '../lib-js') : path.resolve(__dirname, '../src');
  const libDir = process.env.BUNDLE === 'true' ? path.resolve(__dirname, '../lib-js') : path.resolve(__dirname, '../lib');
  replacePath({
    inputDir: srcDir,
    outputDir: libDir,
    // includeExts: DEFAULT_EXTS.concat(['.md']),
    afterReplaced: () => {
      console.log('----------------------------------------------------------------------------------');
      console.log(`| all files import statements been transformed to relative path for ${libDir} ^_^ |`);
      console.log('----------------------------------------------------------------------------------');
    },
  });
})().catch((err) => {
  console.error(err);
  process.exit(-1);
});

引入rollup配置文件

根目录下新增rollup.config.js文件,内容如下:

:::tip 此步骤为可选项
不需要发包到npm时(即使用方不需要静态导入和类型提示功能时),可以跳过此步骤
:::

import typescript from 'rollup-plugin-typescript';
import { terser } from 'rollup-plugin-terser';
import { cst } from 'hel-dev-utils';
import pkg from './package.json';
const env = process.env.BUILD_ENV || 'umd';
const plugins = [
  typescript({
    exclude: 'node_modules/**',
    typescript: require('typescript'),
  }),
];
const env2outputConf = {
  es: {
    format: 'es',
    name: pkg.appGroupName,
    file: `${cst.HEL_PROXY_DIR}_es/entry.js`,
  },
  umd: {
    format: 'umd',
    name: pkg.appGroupName,
    file: `${cst.HEL_PROXY_DIR}/entry.js`,
  },
};
const outputObj = env2outputConf[env];
if (process.env.MIN === 'true') {
  plugins.push(terser());
  const [dirName] = outputObj.file.split('/');
  outputObj.file = `${dirName}/entry.min.js`;
}
module.exports = {
  input: 'src/entrance/libTypes.ts',
  plugins,
  output: [
    outputObj,
  ],
};

新增相关构建命令

package.jsonscripts节点下引入相关构建命令

"scripts": {
    "check": "node ./scripts/check.js",
    "build": "npm run build_dist",
    "build_dist": "node scripts/build.js",
    "build_proxy": "npm run build_proxy_umd && npm run build_proxy_es",
    "build_proxy_umd": "tsc & node ./scripts/replaceToRelativePath.js & rollup -c",
    "build_proxy_es": "tsc & node ./scripts/replaceToRelativePath.js & cross-env BUILD_ENV=es rollup -c",
    "build_meta": "node scripts/meta.js",
    "set_home_page": "cross-env-shell HEL_APP_HOME_PAGE=http://127.0.0.1:8080",
    "build_cust": "npm run set_home_page \"npm run build_dist && npm run build_meta\"",
    "check_name": "node ./scripts/check.js",
    "build_priv": "cross-env-shell CHECK_ENV=0 \"npm run check_name && npm run build_dist && npm run build_meta && npm run build_proxy\"",
    "build_priv:hint": "work for custom deploy",
    "build_helpack": "cross-env-shell CHECK_ENV=0 HEL_APP_HOME_PAGE=http://tnfe.cdn/hel/xxx-name_202202021212 \"npm run check_name && npm run build_dist && npm run build_meta && npm run build_proxy\"",
    "build_helpack:hint": "just mock helpack build process to see hel-meta.json result"
  }

:::tip build_dist命令
build_dist命令你原来的webpack构建命令即可,相关命令命名可以自行调整
:::

构建与发布npm

执行以下命令

npm run build 
npm publish

:::tip npm只发布了源码
npm只发布了源码,运行时代码需要自己发布到相关cdn,如已接入helpack则helpack会自动做相关事宜
:::

@HUGY1
Copy link

HUGY1 commented Jun 29, 2023

这个是要求webpack5的吧? webpack4就搞死人了

@fantasticsoul
Copy link
Collaborator

这个是要求webpack5的吧? webpack4就搞死人了

不需要webpack 5

@fantasticsoul fantasticsoul added the documentation Improvements or additions to documentation label Nov 30, 2023
@betawen
Copy link

betawen commented Apr 2, 2024

有封装的cli命令吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

4 participants