<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>前端 &#8211; 岁月细碎点滴快查</title>
	<atom:link href="https://blog.mutadecheng.com/category/%e5%89%8d%e7%ab%af/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.mutadecheng.com</link>
	<description></description>
	<lastBuildDate>Wed, 31 Dec 2025 00:58:56 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
	<item>
		<title>Arm 搭建一套传感器采集系统(基于docker)</title>
		<link>https://blog.mutadecheng.com/2025/09/11/arm-%e6%90%ad%e5%bb%ba%e4%b8%80%e5%a5%97%e4%bc%a0%e6%84%9f%e5%99%a8%e9%87%87%e9%9b%86%e7%b3%bb%e7%bb%9f%e5%9f%ba%e4%ba%8edocker/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Thu, 11 Sep 2025 07:28:57 +0000</pubDate>
				<category><![CDATA[Arm]]></category>
		<category><![CDATA[Blazor]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Iot]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[前端]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=362</guid>

					<description><![CDATA[架构: 数据库: questdb 前端:blazor server 后端:c#控制台(hostserver)  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>架构:</p>



<p>数据库: questdb</p>



<p>前端:blazor server</p>



<p>后端:c#控制台(hostserver)</p>



<p>平台运维:portainer</p>



<p>容器管理</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# 国外
docker run -d -p 9000:9000 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:alpine-sts
  
# 国内(Arm64)
docker run -d -p 9000:9000 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  registry.cn-beijing.aliyuncs.com/muta/portainer-ce:alpine-sts-arm64

# 国内(Amd64)
docker run -d -p 9000:9000 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  registry.cn-beijing.aliyuncs.com/muta/portainer-ce:alpine-sts-amd64" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955"># 国外</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9000</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--restart=always</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/var/run/docker.sock:/var/run/docker.sock</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer_data:/data</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">portainer/portainer-ce:alpine-sts</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #6A9955"># 国内(Arm64)</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9000</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--restart=always</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/var/run/docker.sock:/var/run/docker.sock</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer_data:/data</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/portainer-ce:alpine-sts-arm64</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># 国内(Amd64)</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9000</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--restart=always</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/var/run/docker.sock:/var/run/docker.sock</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">portainer_data:/data</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/portainer-ce:alpine-sts-amd64</span></span></code></pre></div>



<p>数据库安装</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# 国外
docker run -d \
  --name questdb \
  -p 8812:8812 \
  -p 9080:9000 \
  -p 9009:9009 \
  -v questdb_data:/root/.questdb/db \
  questdb/questdb:nightly-rhel
  
# 国内(Arm64)
docker run -d \
  --name questdb \
  -p 8812:8812 \
  -p 9080:9000 \
  -p 9009:9009 \
  -v questdb_data:/root/.questdb/db \
  registry.cn-beijing.aliyuncs.com/muta/questdb:nightly-rhel-arm64

# 国内(Amd64)
docker run -d \
  --name questdb \
  -p 8812:8812 \
  -p 9080:9000 \
  -p 9009:9009 \
  -v questdb_data:/root/.questdb/db \
  registry.cn-beijing.aliyuncs.com/muta/questdb:nightly-rhel-amd64
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955"># 国外</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8812</span><span style="color: #CE9178">:8812</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9080</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9009</span><span style="color: #CE9178">:9009</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb_data:/root/.questdb/db</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">questdb/questdb:nightly-rhel</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #6A9955"># 国内(Arm64)</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8812</span><span style="color: #CE9178">:8812</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9080</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9009</span><span style="color: #CE9178">:9009</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb_data:/root/.questdb/db</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/questdb:nightly-rhel-arm64</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># 国内(Amd64)</span></span>
<span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-d</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--name</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8812</span><span style="color: #CE9178">:8812</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9080</span><span style="color: #CE9178">:9000</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-p</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">9009</span><span style="color: #CE9178">:9009</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">-v</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">questdb_data:/root/.questdb/db</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/questdb:nightly-rhel-amd64</span></span>
<span class="line"></span></code></pre></div>



<p>rabbitmq</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.8'

services:
  mq:
    image: registry.cn-beijing.aliyuncs.com/muta/rabbitmq:management-arm64 
    restart: always 
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq    # 持久化RabbitMQ数据
    ports:
      - &quot;5672:5672&quot;                        # AMQP协议端口，应用程序连接用
      - &quot;15672:15672&quot;                      # 管理后台端口，Web管理界面用
      # 以下端口仅在集群或特殊情况下需要，可选
      # - &quot;25672:25672&quot;                    # 节点间通信端口（集群用）
      # - &quot;4369:4369&quot;                      # Erlang节点发现端口（集群用）
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot; 

volumes:
  rabbitmq_data:                           # 定义持久化数据卷
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.8&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">mq</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/rabbitmq:management-arm64</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">rabbitmq_data:/var/lib/rabbitmq</span><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># 持久化RabbitMQ数据</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;5672:5672&quot;</span><span style="color: #D4D4D4">                        </span><span style="color: #6A9955"># AMQP协议端口，应用程序连接用</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;15672:15672&quot;</span><span style="color: #D4D4D4">                      </span><span style="color: #6A9955"># 管理后台端口，Web管理界面用</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955"># 以下端口仅在集群或特殊情况下需要，可选</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955"># - &quot;25672:25672&quot;                    # 节点间通信端口（集群用）</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955"># - &quot;4369:4369&quot;                      # Erlang节点发现端口（集群用）</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">rabbitmq_data</span><span style="color: #D4D4D4">:                           </span><span style="color: #6A9955"># 定义持久化数据卷</span></span>
<span class="line"></span></code></pre></div>



<p>采集程序(方案1)</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.8'

services:
  armcollection2025masablazorapp:
    image: registry.cn-beijing.aliyuncs.com/dfzh/armcollection2025masablazorapp:latest
    ports:
      - &quot;20000:8080&quot;
    user: root
    devices:
      - /dev/ttyS3:/dev/ttyS3
    environment: 
      SqlSugar__1__ConnectionString: &quot;host=host.docker.internal;port=8812;username=admin;password=quest;database=qdb;ServerCompatibilityMode=NoTypeLoading;&quot;
    restart: always
    volumes: 
      - /home/orangepi/DataProtection-Keys/:/app/.aspnet/DataProtection-Keys
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.8&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">armcollection2025masablazorapp</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/armcollection2025masablazorapp:latest</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;20000:8080&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">user</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">root</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">devices</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/dev/ttyS3:/dev/ttyS3</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">: </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SqlSugar__1__ConnectionString</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;host=host.docker.internal;port=8812;username=admin;password=quest;database=qdb;ServerCompatibilityMode=NoTypeLoading;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">: </span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/home/orangepi/DataProtection-Keys/:/app/.aspnet/DataProtection-Keys</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span></code></pre></div>



<p>采集程序(方案2)</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.8'

services:
  app:
    image: registry.cn-beijing.aliyuncs.com/dfzh/armcollectblazorapp:latest
    network_mode: &quot;host&quot; 
    environment:  
      Urls: &quot;http://*:20000&quot;
    restart: always 
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;
        
  serialport2questdb:
    image: registry.cn-beijing.aliyuncs.com/dfzh/armcollectserialport2questdb:latest
    network_mode: &quot;host&quot; 
    user: root
    devices:
      - /dev/ttyS3:/dev/ttyS3
    environment:  
      ComPortName : &quot;/dev/ttyS3&quot;
      Urls: &quot;http://*:20002&quot; 
    restart: always 
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.8&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">app</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/armcollectblazorapp:latest</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">network_mode</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;host&quot;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:  </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">Urls</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;http://*:20000&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">serialport2questdb</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/armcollectserialport2questdb:latest</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">network_mode</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;host&quot;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">user</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">root</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">devices</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/dev/ttyS3:/dev/ttyS3</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:  </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">ComPortName</span><span style="color: #D4D4D4"> : </span><span style="color: #CE9178">&quot;/dev/ttyS3&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">Urls</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;http://*:20002&quot;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.8'

services:
  app:
    image: registry.cn-beijing.aliyuncs.com/dfzh/staticforcecalibration-blazorserver:arm64
    restart: always 
    volumes:
      - /home/bjgrst/staticforcecalibration_data:/app/App_Data     
      - /home/bjgrst/DefaultSeedsJsonFiles/:/app/DefaultSeedsJsonFiles
      - /dev:/dev
    ports:
      - &quot;8080:8080&quot;      
    user: root
    privileged: true
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot; 
 
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.8&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">app</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/staticforcecalibration-blazorserver:arm64</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/home/bjgrst/staticforcecalibration_data:/app/App_Data</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/home/bjgrst/DefaultSeedsJsonFiles/:/app/DefaultSeedsJsonFiles</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/dev:/dev</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;8080:8080&quot;</span><span style="color: #D4D4D4">      </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">user</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">root</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">privileged</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">true</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"></span></code></pre></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Blazor 项目中集成 NPM 包与 TypeScript，并用 ESBuild 打包的实战与原理</title>
		<link>https://blog.mutadecheng.com/2025/07/14/blazor-%e9%a1%b9%e7%9b%ae%e4%b8%ad%e9%9b%86%e6%88%90-npm-%e5%8c%85%e4%b8%8e-typescript%ef%bc%8c%e5%b9%b6%e7%94%a8-esbuild-%e6%89%93%e5%8c%85%e7%9a%84%e5%ae%9e%e6%88%98%e4%b8%8e%e5%8e%9f%e7%90%86/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Mon, 14 Jul 2025 09:22:13 +0000</pubDate>
				<category><![CDATA[Blazor]]></category>
		<category><![CDATA[前端]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=339</guid>

					<description><![CDATA[一、ESM 与 UMD 模块格式的区别 现代 JavaScript 生态主要有两种流行的模块格式：ESM（EC [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">一、ESM 与 UMD 模块格式的区别</h3>



<p>现代 JavaScript 生态主要有两种流行的模块格式：ESM（ECMAScript Module）和 UMD（Universal Module Definition）。</p>



<h4 class="wp-block-heading">1. ESM（ECMAScript Module）</h4>



<ul class="wp-block-list">
<li>使用 <code>import</code> 和 <code>export</code> 关键字进行模块组织。</li>



<li>加载方式为静态加载，编译时即可确定依赖关系。</li>



<li>适用于现代浏览器和支持 ES Module 的 Node.js 版本。</li>



<li>支持 Tree Shaking，未被引用的代码可在打包时去除，减小体积。</li>



<li>依赖关系明确，易于优化和静态分析。</li>



<li>原生支持异步加载（浏览器端）。</li>



<li>常见扩展名为 <code>.mjs</code> 或 <code>.js</code>。</li>
</ul>



<p><strong>示例：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="// a.js
export function foo() {}

// b.js
import { foo } from './a.js';" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// a.js</span></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">foo</span><span style="color: #D4D4D4">() {}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">// b.js</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">foo</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;./a.js&#39;</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<h4 class="wp-block-heading">2. UMD（Universal Module Definition）</h4>



<ul class="wp-block-list">
<li>兼容 CommonJS、AMD 和浏览器全局变量等多种模块系统。</li>



<li>运行时自动判断当前环境（Node.js、浏览器、AMD）。</li>



<li>几乎可在所有 JS 环境下直接使用，包括老旧浏览器。</li>



<li>最大的优点是兼容性好，可以直接用 <code>&lt;script&gt;</code> 标签引入。</li>



<li>缺点是不能静态分析依赖，Tree Shaking 效果差，体积略大。</li>
</ul>



<p><strong>示例：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="(function (root, factory) {
  if (typeof define === 'function' &amp;&amp; define.amd) {
    define([], factory);
  } else if (typeof module === 'object' &amp;&amp; module.exports) {
    module.exports = factory();
  } else {
    root.myLib = factory();
  }
}(this, function () {
  return {};
}));" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">(</span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">root</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">factory</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">typeof</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">define</span><span style="color: #D4D4D4"> === </span><span style="color: #CE9178">&#39;function&#39;</span><span style="color: #D4D4D4"> &amp;&amp; </span><span style="color: #9CDCFE">define</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">amd</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">define</span><span style="color: #D4D4D4">([], </span><span style="color: #9CDCFE">factory</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">typeof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">module</span><span style="color: #D4D4D4"> === </span><span style="color: #CE9178">&#39;object&#39;</span><span style="color: #D4D4D4"> &amp;&amp; </span><span style="color: #4EC9B0">module</span><span style="color: #D4D4D4">.</span><span style="color: #4EC9B0">exports</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4EC9B0">module</span><span style="color: #D4D4D4">.</span><span style="color: #4EC9B0">exports</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">factory</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">  } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">root</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">myLib</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">factory</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"><span style="color: #D4D4D4">}(</span><span style="color: #569CD6">this</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> () {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> {};</span></span>
<span class="line"><span style="color: #D4D4D4">}));</span></span></code></pre></div>



<h4 class="wp-block-heading">3. 对比总结</h4>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>特点</th><th>ESM</th><th>UMD</th></tr></thead><tbody><tr><td>兼容性</td><td>现代浏览器/Node.js</td><td>各种环境（浏览器、Node等）</td></tr><tr><td>语法</td><td>import/export</td><td>兼容多种模块系统</td></tr><tr><td>Tree Shaking</td><td>支持</td><td>不支持</td></tr><tr><td>用途</td><td>新项目推荐</td><td>兼容老环境或全局变量场景</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">二、Blazor 与 ESM/UMD 的集成限制</h3>



<p>Blazor 是微软推出的 Web 前端开发框架，支持 C# 编写客户端逻辑，分为 Blazor WebAssembly 和 Blazor Server 两种模式。Blazor 本身可以通过 JS interop 机制与 JavaScript 交互，但在集成现代 JS 库时存在以下局限：</p>



<h4 class="wp-block-heading">1. Blazor 的 JS 交互方式</h4>



<ul class="wp-block-list">
<li>只能通过 JS interop 调用全局作用域下的 JS 函数（即挂在 <code>window</code> 上的方法）。</li>



<li>无法直接使用 <code>import</code> 语法动态加载 ESM 模块（除非用 <code>&lt;script type="module"&gt;</code> 并手动挂载到 <code>window</code>）。</li>



<li>不能像 React/Vue 那样直接使用 NPM 包或通过模块系统自动管理依赖。</li>
</ul>



<h4 class="wp-block-heading">2. ESM/UMD 直接集成的障碍</h4>



<ul class="wp-block-list">
<li>ESM 格式的库必须通过 <code>import</code> 加载，Blazor 无法直接识别，也无法在 C# 代码中直接调用。</li>



<li>UMD 虽可全局挂载，但许多 UMD 库默认不会主动把 API 挂到 <code>window</code>，需要额外封装。</li>



<li>Blazor 的 JS interop 通信方式决定了只能通过全局对象与 JS 交互，无法像前端框架一样灵活集成 NPM 生态。</li>
</ul>



<h4 class="wp-block-heading">3. 正确的集成方式</h4>



<ul class="wp-block-list">
<li>手动引入 JS 文件：在 <code>wwwroot/index.html</code> 用 <code>&lt;script&gt;</code> 标签引入 UMD 格式库，并确保需要的 API 挂载到 <code>window</code>。</li>



<li>封装全局 JS 方法：写一段 JS 代码，把第三方库的核心方法挂到 <code>window</code>，便于 Blazor 调用。</li>



<li>如果必须使用 ESM，需用 <code>&lt;script type="module"&gt;</code> 并手动挂到 <code>window</code>，否则 Blazor 访问不到。</li>
</ul>



<p><strong>示例：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="<script src=&quot;your-umd-lib.js&quot;&gt;</script&gt;
<script&gt;
  window.myLib = window.myLib || {}; // 确保全局可访问
</script&gt;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #808080">&lt;</span><span style="color: #569CD6">script</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">src</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;your-umd-lib.js&quot;</span><span style="color: #808080">&gt;&lt;/</span><span style="color: #569CD6">script</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #808080">&lt;</span><span style="color: #569CD6">script</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">window</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">myLib</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">window</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">myLib</span><span style="color: #D4D4D4"> || {}; </span><span style="color: #6A9955">// 确保全局可访问</span></span>
<span class="line"><span style="color: #808080">&lt;/</span><span style="color: #569CD6">script</span><span style="color: #808080">&gt;</span></span></code></pre></div>



<p>Blazor 代码则通过 JS interop 调用 <code>window.myLib.xxx</code> 方法。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">三、在 Blazor 中集成 NPM 包与 TypeScript 的现代实践</h3>



<p>面对 ESM/UMD 集成难题，推荐以下现代化方案：</p>



<div class="wp-block-visualize-mermaid"><pre class="visualizeMermaid__content js-visualize-content">上述</pre><pre class="visualizeMermaid__error visualizeMermaid__error--hidden js-visualize-error">Parse error on line 1:
上述
^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'UNICODE_TEXT'</pre><div class="visualizeMermaid__canvas"></div></div>



<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">flowchart TD
    A[开始：Blazor 项目] --> B[NPM 安装 esbuild 和所需 JS 库]
    B --> C[编写 TypeScript 文件&lt;br>（如 Scripts/components.ts）]
    C --> D[在 package.json 配置 esbuild 打包脚本]
    D --> E[运行 npm run debugBuild / releaseBuild]
    E --> F[esbuild 打包 TypeScript 和 NPM 依赖&lt;br>输出到 wwwroot/js/components.js]
    F --> G[Blazor 组件中通过 JS Interop 动态 import]
    G --> H[调用 JS 方法实现 C# 与 JS 互操作]
    H --> I[自动化集成到 .csproj 构建流程]
    I --> J[完成]
</pre></div>



<h4 class="wp-block-heading">1. 使用 ESBuild 编译 TypeScript 和打包 NPM 依赖</h4>



<div class="wp-block-visualize-mermaid"><pre class="visualizeMermaid__content js-visualize-content">的法国队</pre><pre class="visualizeMermaid__error visualizeMermaid__error--hidden js-visualize-error">Parse error on line 1:
的法国队
^
Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'UNICODE_TEXT'</pre><div class="visualizeMermaid__canvas"></div></div>



<ul class="wp-block-list">
<li>在项目根目录下用 NPM 安装 ESBuild 和所需的 JS 库。</li>



<li>在 <code>Scripts</code> 目录下编写 TypeScript 集成代码，导入 NPM 包并封装为供 Blazor 调用的全局方法。</li>



<li>在 <code>package.json</code> 配置 ESBuild 打包脚本，输出为 ESM 格式的单一 JS 文件到 <code>wwwroot/js</code>。</li>



<li>Blazor 组件通过 <code>IJSRuntime</code> 动态导入打包后的模块，直接调用自定义方法。</li>
</ul>



<p><strong>关键脚本示例：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&quot;scripts&quot;: {
    &quot;debugBuild&quot;: &quot;esbuild ./Scripts/components.ts --format=esm --bundle --sourcemap --outdir=wwwroot/js&quot;,
    &quot;releaseBuild&quot;: &quot;esbuild ./Scripts/components.ts --format=esm --bundle --sourcemap --minify --outdir=wwwroot/js&quot;
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #CE9178">&quot;scripts&quot;</span><span style="color: #D4D4D4">: {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;debugBuild&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;esbuild ./Scripts/components.ts --format=esm --bundle --sourcemap --outdir=wwwroot/js&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;releaseBuild&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;esbuild ./Scripts/components.ts --format=esm --bundle --sourcemap --minify --outdir=wwwroot/js&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h4 class="wp-block-heading">2. 自动化集成到 .NET 构建流程</h4>



<ul class="wp-block-list">
<li>在 <code>.csproj</code> 文件中添加 NPM 安装和打包任务，确保每次 <code>dotnet build</code> 或 <code>dotnet run</code> 时自动完成依赖安装和打包。</li>
</ul>



<p><strong>示例：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="<Target Name=&quot;NPM Install&quot; AfterTargets=&quot;PreBuildEvent&quot;&gt;
    <Exec Command=&quot;npm install&quot; /&gt;
</Target&gt;
<Target Name=&quot;NPM Debug Build&quot; AfterTargets=&quot;NPM Install&quot; Condition=&quot;$(Configuration) == 'DEBUG'&quot;&gt;
    <Exec Command=&quot;npm run debugBuild&quot; /&gt;
</Target&gt;
<Target Name=&quot;NPM Release Build&quot; AfterTargets=&quot;NPM Install&quot; Condition=&quot;$(Configuration) == 'RELEASE'&quot;&gt;
    <Exec Command=&quot;npm run releaseBuild&quot; /&gt;
</Target&gt;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">Target</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;NPM Install&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">AfterTargets</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;PreBuildEvent&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;</span><span style="color: #9CDCFE">Exec</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Command</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;npm install&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">Target</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #9CDCFE">Target</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;NPM Debug Build&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">AfterTargets</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;NPM Install&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Condition</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;$(Configuration) == &#39;DEBUG&#39;&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;</span><span style="color: #9CDCFE">Exec</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Command</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;npm run debugBuild&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">Target</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #9CDCFE">Target</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;NPM Release Build&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">AfterTargets</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;NPM Install&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Condition</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;$(Configuration) == &#39;RELEASE&#39;&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;</span><span style="color: #9CDCFE">Exec</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Command</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;npm run releaseBuild&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">Target</span><span style="color: #D4D4D4">&gt;</span></span></code></pre></div>



<h4 class="wp-block-heading">3. Blazor 组件调用方式</h4>



<ul class="wp-block-list">
<li>通过 <code>IJSRuntime.InvokeAsync&lt;IJSObjectReference&gt;("import", "./js/components.js")</code> 动态加载模块。</li>



<li>直接调用打包后暴露的 JS 方法，实现 C# 与 JS 的高效互操作。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">四、总结</h3>



<p>ESM 格式适合现代前端开发，支持静态分析和 Tree Shaking，但不支持直接在 Blazor 中模块化调用。UMD 格式兼容性强，可通过全局变量方式间接集成到 Blazor，但需要手动挂载 API。通过引入 ESBuild 工具，将 TypeScript 和所有 NPM 依赖打包为适合 Blazor 动态加载的 ESM 文件，并结合 JS interop 机制，Blazor 项目能够高效利用现代 JavaScript 生态，实现类型安全、依赖清晰的前后端集成开发。</p>



<h3 class="wp-block-heading">五、引用资料</h3>



<p>1.博客:<a href="https://blog.dymaptic.com/using-esbuild-with-blazor">Using ESBuild with Blazor</a></p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
