didi / mpx

Mpx,一款具有优秀开发体验和深度性能优化的增强型跨端小程序框架
https://mpxjs.cn
Apache License 2.0
3.63k stars 378 forks source link

[Bug report] defs 变量改变以后 build 结果不一致 #1652

Open outman opened 1 month ago

outman commented 1 month ago

问题描述
请用简洁的语言描述你遇到的bug,至少包括以下部分,如提供截图请尽量完整:

  1. 问题触发的条件 进行自定义 defs 变量

    defs: {
    __mpx_domain__: process.env.DOMAIN
    }
  2. 期望的表现 __mpx_domain__ 值在使用的时候是期望的值。

  3. 实际的表现 DOMAIN 环境变量一开始是 A,再改为 B 以后,build 结果生成的文件中就会即有 A 又有 B。

环境信息描述
至少包含以下部分:

  1. 系统类型(Mac)
  2. Mpx依赖版本(@mpxjs/core、@mpxjs/webpack-plugin和@mpxjs/api-proxy的具体版本,可以通过package-lock.json或者实际去node_modules当中查看)
    "dependencies": {
    "@mpxjs/api-proxy": "^2.9.0",
    "@mpxjs/core": "^2.9.0",
    "@mpxjs/fetch": "^2.9.0",
    "@mpxjs/pinia": "^2.9.0",
    "@mpxjs/store": "^2.9.0",
    "@mpxjs/utils": "^2.9.0",
    "pinia": "^2.0.14",
    "vue": "^2.7.0",
    "vue-demi": "^0.14.6",
    "vue-i18n": "^8.27.2",
    "vue-i18n-bridge": "^9.2.2",
    "vue-router": "^3.1.3"
    },
    "devDependencies": {
    "@babel/core": "^7.10.4",
    "@babel/plugin-transform-runtime": "^7.10.4",
    "@babel/preset-env": "^7.10.4",
    "@babel/runtime-corejs3": "^7.10.4",
    "@mpxjs/babel-plugin-inject-page-events": "^2.9.0",
    "@mpxjs/eslint-config": "^1.0.5",
    "@mpxjs/mpx-cli-service": "^2.0.0",
    "@mpxjs/size-report": "^2.9.0",
    "@mpxjs/vue-cli-plugin-mpx": "^2.0.0",
    "@mpxjs/vue-cli-plugin-mpx-eslint": "^2.0.0",
    "@mpxjs/webpack-plugin": "^2.9.0",
    "@vue/cli-service": "~5.0.0",
    "autoprefixer": "^10.2.4",
    "eslint": "^7.0.0",
    "postcss": "^8.2.6",
    "stylus": "^0.55.0",
    "stylus-loader": "^6.1.0",
    "webpack": "^5.43.0"
    },
  3. 小程序开发者工具信息(小程序平台、开发者工具版本、基础库版本)

最简复现demo
view 代码部分

<view
      wx:for="{{listData}}"
      wx:for-index="index"
      wx:key="*this"
      wx:for-item="item"
      class="section"
    >
      <view class="title">{{ item.title }}</view>
      <view
        class="card"
        wx:for="{{item.items}}"
        wx:for-index="subIndex"
        wx:key="*this"
        wx:for-item="subItem"
      >
        <view>
          <image src="{{__mpx_domain__}}{{subItem.images}}.avif"
            mode="aspectFit"
            lazy-load="{{true}}"
            bindtap="previewImageTap(subItem.images)"
          ></image
        ></view>
        <view class="sub-title">{{ subItem.subTitle }}</view>
      </view>
    </view>

script 代码部分

<script>
import mpx, { createComponent } from '@mpxjs/core'
import { data } from '../lib/store'

createComponent({
  data: {
    listData: data
  },
  methods: {
    previewImageTap(url) {
      /* eslint-disable camelcase */
      console.log(__mpx_domain__ + url)
      mpx.previewImage({
        /* eslint-disable camelcase */
        urls: [__mpx_domain__ + url]
      })
    }
  }
})
</script>

删除 .cache 和 dist 以后重新 build 就好了。

hiyuki commented 1 month ago

这个defs是在哪个文件中定义的? 是vue.config.js中吗?

outman commented 1 month ago

这个defs是在哪个文件中定义的? 是vue.config.js中吗?

@hiyuki 是的。

mpx: {
      plugin: {
        // mode: 'web',
        srcMode: 'wx',
        hackResolveBuildDependencies: ({ files, resolveDependencies }) => {
          const path = require('path')
          const packageJSONPath = path.resolve('package.json')
          if (files.has(packageJSONPath)) files.delete(packageJSONPath)
          if (resolveDependencies.files.has(packageJSONPath)) {
            resolveDependencies.files.delete(packageJSONPath)
          }
        },
        defs: {
          __mpx_domain__: process.env.DOMAIN
        }
      },
      loader: {}
    }
mater1996 commented 1 month ago

DOMAIN 是如何声明的?

outman commented 1 month ago

DOMAIN 是如何声明的?

@mater1996 在命令行 export DOMAIN=xxxx

mater1996 commented 1 month ago

DOMAIN 是如何声明的?

@mater1996 在命令行 export DOMAIN=xxxx

给提供一个仓库吧,我本地没有复现这个问题

outman commented 1 month ago

DOMAIN 是如何声明的?

@mater1996 在命令行 export DOMAIN=xxxx

给提供一个仓库吧,我本地没有复现这个问题

@mater1996 https://github.com/outman/modern-art

outman commented 1 month ago

DOMAIN 是如何声明的?

@mater1996 在命令行 export DOMAIN=xxxx

给提供一个仓库吧,我本地没有复现这个问题

@mater1996 https://github.com/outman/modern-art 复现步骤: 去掉 vue.config.json mode: 'web' 的注释

  1. 在 命令行 export DOMAIN=https://okai.dev
  2. pnpm build:cross
  3. 再次在命令行 export DOMAIN=https://example.com
  4. pnpm build:cross

之后在 dist/web 目录下,搜索文件内这两个域名,都会出现。而且将 dist/web 部署以后就发现一部分请求了第 1 步的域名,一部分请求了第 2 步的域名。

mater1996 commented 1 month ago

这块跟vue.config.js这段配置有关系

hackResolveBuildDependencies: ({ files, resolveDependencies }) => {
    const path = require('path')
    const packageJSONPath = path.resolve('package.json')
    if (files.has(packageJSONPath)) files.delete(packageJSONPath)
    if (resolveDependencies.files.has(packageJSONPath)) {
       resolveDependencies.files.delete(packageJSONPath)
    }
},

package.json变动依旧会采用缓存的内容,所以环境变量需要写到vue.config.js里,这样环境变量变动就可以使缓存失效。 或者一定要写到package.json里,那么需要修改webpackConfigname根据你的环境变量来变化,隔离不同的环境缓存。 例如

configureWebpack(config) {
    return {
      name: process.env.DOMAIN
    }
}