elfennol/env-to-js-symfony-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

elfennol/env-to-js-symfony-bundle

Composer 安装命令:

composer require elfennol/env-to-js-symfony-bundle

包简介

Inject Symfony .env variables into the browser at runtime via typed script tags

README 文档

README

Inject Symfony .env variables into the browser at runtime, via <script type="application/json"> tags read by the @elfennol/env-to-js TypeScript package.

BEFORE  build(staging) → app.staging.js   ← rebuild required for each environment
        build(prod)    → app.prod.js

AFTER   build() → app.js                  ← one artifact, promoted as-is
        On each request, Symfony adds to the HTML:
        <script type="application/json" id="rc-app">{"apiBaseUrl":"https://api.example.com"}</script>

The problem

In a Symfony + JavaScript application, variables from .env often need to reach the browser (API URLs, third-party keys, feature flags, etc.). The common solution is to bake them in at build time via DefinePlugin (Webpack) or define (Vite).

Consequences:

  • The build artifact is tied to one environment — promoting from staging to prod requires a full rebuild
  • Rotating a key or changing config requires a full frontend rebuild and redeployment
  • Frontend variables and Symfony .env become two separate systems to maintain

The solution

env-to-js lets Symfony inject .env variables into the HTML at runtime, as typed <script type="application/json"> tags read by a zero-dependency TypeScript reader.

Installation

composer require elfennol/env-to-js-symfony-bundle
npm install @elfennol/env-to-js

Setup

1. Add the Twig block to your base template

{# templates/base.html.twig #}
{% block env_to_js %}
    {{ env_to_js_scripts()|raw }}
{% endblock %}

2. Create a provider

// src/Config/AppConfigProvider.php
namespace App\Config;

use Elfennol\EnvToJs\ConfigProviderInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Request;

final class AppConfigProvider implements ConfigProviderInterface
{
    public function __construct(
        #[Autowire(env: 'API_BASE_URL')] private string $apiBaseUrl,
        #[Autowire(env: 'CDN_BASE_URL')] private string $cdnBaseUrl,
    ) {}

    public function supports(Request $request): bool { return true; }
    public function getScope(): string { return 'app'; }

    public function getConfig(): array
    {
        return [
            'apiBaseUrl' => $this->apiBaseUrl,
            'cdnBaseUrl' => $this->cdnBaseUrl,
        ];
    }
}

No registration needed — any class implementing ConfigProviderInterface is auto-tagged.

Conditional providers

A provider that only runs on specific pages inspects the request:

final class MapConfigProvider implements ConfigProviderInterface
{
    public function __construct(
        #[Autowire(env: 'MAP_API_KEY')] private string $mapApiKey,
        #[Autowire(env: 'MAP_ID')] private string $mapId,
    ) {}

    public function supports(Request $request): bool
    {
        return in_array($request->attributes->get('_route'), ['app_map_index', 'app_map_show'], true);
    }

    public function getScope(): string { return 'map'; }

    public function getConfig(): array
    {
        return [
            'mapApiKey' => $this->mapApiKey,
            'mapId'     => $this->mapId,
        ];
    }
}

The <script id="rc-map"> tag is injected only on the matched routes.

Configuration

# config/packages/env_to_js.yaml
env_to_js:
    id_prefix: 'rc-'  # default

The injected tag id is {id_prefix}{scope}. Pass the same value as the selector to createConfigReader().

Scope collision

If two active providers return the same scope, their configs are merged with array_merge. Last registered wins on key conflict.

Migration guides

From DefinePlugin / process.env

  1. Remove the configureDefinePlugin block from your Webpack config (or define from your Vite config).
  2. Group your formerly-injected variables into one or several ConfigProviderInterface providers.
  3. Replace each process.env.MY_VAR in your source code with getAppConfig('myVar') (the getter returned by createConfigReader).

Your webpack/vite artifact is now environment-agnostic — one build, promoted from staging to prod without a rebuild.

From window.* or data-options attributes

  1. Create ConfigProviderInterface providers for each group of variables currently assigned on window or in data-* attributes.
  2. Replace window.myVariable accesses with getAppConfig('myVariable') (the getter returned by createConfigReader).
  3. Remove the inline <script> or data-* injection from your templates.

Requirements

  • PHP >= 8.2
  • Symfony >= 7.4

Development

make qa-vendor-install # install dependencies
make qa                # phpcs + phpstan + phpunit + rector
make help              # list all available commands

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-16

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固