Taro实现动态打包小程序

一套代码打包多个小程序实践

业务场景: 当前维护一个Taro小程序,页面、模块很多,部分功能之间可能并不相关。所以产品提出将该小程序中的部分模块抽离出来,重新打包一个小程序用来推广、拉新。

思考流程

Question & Answer

Q1. 不同小程序可能需要一起维护,不能每次改完这个,还要到另外一个项目中更改。

A1: 很好解决,直接在同一个项目中进行维护,不对具体模块进行拆分。

  1. 不同小程序的首页不同。在主体的小程序中,可能并不需要其他小程序中的首页。

A2: 首页的问题直接可以通过小程序打包的管理后台进行设置相应的路径,就可以设置首页了 或者 将首页路径配置为主包的第一个路径。

  1. 在其他小程序中也可能不需要主题小程序中的部分页面;聚合的小程序主包体积过大。

A3: 具体小程序不需要的页面在配置中把具体路径删除就不会打包了。

  1. 首页的路径需要根据具体小程序动态调整。

A4: 设置首页路径变量,该变量根据具体小程序进行判断设置。

  1. 不同小程序之间相关配置不同。

A5: 不同小程序设置不同的配置文件。

以上流程基本就是一次打包需要调整的东西了,但如果每次都这样就会让人很烦躁,而且如果有3个、4个...小程序需要同步维护呢!有没有什么方法优化?怎么优化? 思考ing... 打包之前要改这些文件,那么能不能在打包之前就让程序知道打包的是那个小程序,然后根据这个来判断?从这个思路走,就想到了在平时开发中的 process.env.NODE_ENV、还有通过环境配置 .env .env.developement .env.production等等,设置一些webpack的常量。如此,就清楚了具体需要如何去做接下来的流程。

具体实现流程

首先

process.env.NODE_ENV 的 production、development 是可以通过具体运行的 npm 脚本中 --mode development修改的,因此也通过这种方式在运行具体脚本时设置一个参数用来区分不同小程序。由于我这里是windows电脑,所以要安装cross-env来设置,具体命令如下:

json 复制代码
  "scripts": {
    "build:weapp": "cross-env APP='TEST_APP' taro build --type weapp",
    "dev:weapp": "npm run build:weapp -- --watch",
  },

在 app.config.ts 文件中测试是否设置成功,

php 复制代码
console.log('process.env', process.env.APP);
export default defineAppConfig({
  pages: [
    'pages/index/index'
  ],
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#fff',
    navigationBarTitleText: 'WeChat',
    navigationBarTextStyle: 'black'
  }
})

运行 npm run dev:weapp 后,命令行出现如下结果,就说明设置成功了。 然后在主页面试试获取这个参数,用于去判断其他的代码逻辑。 但在运行时出现了这个错误。 发现是Nodejs中设置的运行时变量,打包后就没法获取了,因此要将这个参数设置为webpack中的一个常量,具体在 webpack 中可以使用 webpack.DefinePlugin 进行设置,但是在 taro 中并不需要这样做,可以直接在 config/index.ts 的配置中直接设置 env 的值。

具体代码如下:

需要注意的是,设置 env 的时候,具体的值需要通过JSON.stringify处理一下,不然会把process.env.APP的值当作一个变量。

ts 复制代码
import { defineConfig, type UserConfigExport } from '@tarojs/cli'
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'
import devConfig from './dev'
import prodConfig from './prod'

console.log('process.env.APP config', process.env.APP);

// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数
export default defineConfig(async (merge, { command, mode }) => {
  const baseConfig: UserConfigExport = {
    projectName: 'taro-app-test',
    date: '2024-1-12',
    designWidth: 750,
    deviceRatio: {
      640: 2.34 / 2,
      750: 1,
      375: 2,
      828: 1.81 / 2
    },
    env: {
      APP: JSON.stringify(process.env.APP)
    },
    sourceRoot: 'src',
    outputRoot: 'dist',
    plugins: [],
    defineConstants: {
    },
    copy: {
      patterns: [
      ],
      options: {
      }
    },
    framework: 'react',
    compiler: 'webpack5',
    cache: {
      enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
    },
    mini: {
      postcss: {
        pxtransform: {
          enable: true,
          config: {

          }
        },
        url: {
          enable: true,
          config: {
            limit: 1024 // 设定转换尺寸上限
          }
        },
        cssModules: {
          enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
          config: {
            namingPattern: 'module', // 转换模式,取值为 global/module
            generateScopedName: '[name]__[local]___[hash:base64:5]'
          }
        }
      },
      webpackChain(chain) {
        chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
      }
    },
    h5: {
      publicPath: '/',
      staticDirectory: 'static',
      output: {
        filename: 'js/[name].[hash:8].js',
        chunkFilename: 'js/[name].[chunkhash:8].js'
      },
      miniCssExtractPluginOption: {
        ignoreOrder: true,
        filename: 'css/[name].[hash].css',
        chunkFilename: 'css/[name].[chunkhash].css'
      },
      postcss: {
        autoprefixer: {
          enable: true,
          config: {}
        },
        cssModules: {
          enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
          config: {
            namingPattern: 'module', // 转换模式,取值为 global/module
            generateScopedName: '[name]__[local]___[hash:base64:5]'
          }
        }
      },
      webpackChain(chain) {
        chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin)
      }
    },
    rn: {
      appName: 'taroDemo',
      postcss: {
        cssModules: {
          enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
        }
      }
    }
  }
  if (process.env.NODE_ENV === 'development') {
    // 本地开发构建配置(不混淆压缩)
    return merge({}, baseConfig, devConfig)
  }
  // 生产构建配置(默认开启压缩混淆等)
  return merge({}, baseConfig, prodConfig)
})

然后再次看首页能否拿到具体的 process.env.APP

这样下来已经差不多了,剩下的就是对动态打包进行处理的。

动态打包📦

经过如上流程,动态打包应该是很容易了,只需要通过 process.env.APP 的值在 app.config.ts 的配置文件中,动态的配置主包pages、分包pages...就能够动态打包了。了解具体需要怎么做,接下来就开始进行实践!

具体代码如下:

php 复制代码
import { TEST_APP } from "./constants/app-type";

const pages = ["pages/index/index", "pages/bbb/index"];

const packageA_pages = ["pages/aaa/index", "pages/demo/index"]

if(process.env.APP === TEST_APP) {
  pages.unshift("pages/test/index")
  packageA_pages.push("pages/testa/index")
}

export default defineAppConfig({
  pages: pages,
  subPackages: [
    {
      root: "packageA",
      pages: packageA_pages,
    },
  ],
  window: {
    backgroundTextStyle: "light",
    navigationBarBackgroundColor: "#fff",
    navigationBarTitleText: "WeChat",
    navigationBarTextStyle: "black",
  },
});

接下来看下具体打包有什么差异。

正常打包后的文件目录:

配置过后打包的文件目录:

可以清楚的看到,在某个小程序中不需要的页面就没有被打包到该小程序中了,就这样解决了上面遇到的问题,开发完成发布时,也不需要去修改文件了,只需要对 app.config.ts 中进行相应的配置就可以了,而且还能够支持打包更多的小程序。

项目文件结构如下:

lua 复制代码
├── __tests__
│   └── index.test.js
├── babel.config.js
├── config
│   ├── dev.ts
│   ├── index.ts
│   └── prod.ts
├── jest.config.ts
├── package.json
├── project.config.json
├── project.tt.json
├── src
│   ├── app.config.ts
│   ├── app.scss
│   ├── app.ts
│   ├── constants
│   │   └── app-type.ts
│   ├── index.html
│   ├── packageA
│   │   ├── components
│   │   └── pages
│   │       ├── aaa
│   │       ├── demo
│   │       └── testa
│   └── pages
│       ├── bbb
│       │   ├── index.config.ts
│       │   ├── index.module.scss
│       │   └── index.tsx
│       ├── index
│       │   ├── index.config.ts
│       │   ├── index.scss
│       │   └── index.tsx
│       └── test
│           ├── index.config.ts
│           ├── index.scss
│           └── index.tsx
├── tsconfig.json
├── types
│   └── global.d.ts
└── yarn.lock

总结

无用的废话哈哈哈。通过这次实践了解了一些关于打包流程上的东西,学习了打包命令中的参数配置,并解决了打包多个小程序中无用代码&...问题,也算是一个不小的收获吧。

相关推荐
Myli_ing21 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风23 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟32 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript