跳到内容

Encore:设置您的项目

编辑此页

安装 Encore后,您的应用已经有一些文件,组织在 assets/ 目录下

  • assets/app.js
  • assets/styles/app.css

使用 Encore,将您的 app.js 文件视为一个独立的 JavaScript 应用程序:它将引入所有需要的依赖项(例如 jQuery 或 React),包括任何 CSS。您的 app.js 文件已经通过 JavaScript import 语句实现了这一点

1
2
3
4
// assets/app.js
// ...

import './styles/app.css';

Encore 的工作(通过 Webpack)很简单:读取并遵循所有的 import 语句,并创建一个最终的 app.js(和 app.css),其中包含您的应用所需的一切。Encore 可以做更多的事情:压缩文件,预处理 Sass/LESS,支持 React、Vue.js 等。

配置 Encore/Webpack

Encore 中的一切都通过项目根目录下的 webpack.config.js 文件进行配置。它已经包含了您需要的基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// webpack.config.js
const Encore = require('@symfony/webpack-encore');

Encore
    // directory where compiled assets will be stored
    .setOutputPath('public/build/')
    // public path used by the web server to access the output path
    .setPublicPath('/build')

    .addEntry('app', './assets/app.js')

    // uncomment this if you want use jQuery in the following example
    .autoProvidejQuery()
;

// ...

关键部分是 addEntry():这告诉 Encore 加载 assets/app.js 文件并遵循所有的 require() 语句。然后它会将所有内容打包在一起,并 - 由于第一个 app 参数 - 将最终的 app.jsapp.css 文件输出到 public/build 目录中。

如果您使用 npm 包管理器,请运行以下命令来构建 assets

1
2
3
4
5
6
7
8
9
10
11
# compile assets and automatically re-compile when files change
$ npm run watch

# or, run a dev-server that can sometimes update your code without refreshing the page
$ npm run dev-server

# compile assets once
$ npm run dev

# on deploy, create a production build
$ npm run build

所有这些命令 - 例如 devwatch - 都是在您的 package.json 文件中定义的快捷方式。

提示

如果您正在使用 Symfony CLI 工具,您可以配置 worker 与 web 服务器一起自动运行。您可以在 Symfony CLI Workers 文档中找到更多信息。

警告

每当您在 webpack.config.js 文件中进行更改时,您必须停止并重新启动 encore

恭喜!您现在有三个新文件

  • public/build/app.js (包含您的 "app" 入口的所有 JavaScript)
  • public/build/app.css (包含您的 "app" 入口的所有 CSS)
  • public/build/runtime.js (一个帮助 Webpack 完成其工作的文件)

注意

实际上,您可能在 public/build 中有更多文件。其中一些是由于代码分割,这是一种有助于提高性能的优化,但不会影响事物的运作方式。其他的则帮助 Encore 完成其工作。

接下来,要将这些包含在您的基础布局中,您可以利用 WebpackEncoreBundle 中的两个 Twig 助手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{# templates/base.html.twig #}
<!DOCTYPE html>
<html>
    <head>
        <!-- ... -->

        {% block stylesheets %}
            {# 'app' must match the first argument to addEntry() in webpack.config.js #}
            {{ encore_entry_link_tags('app') }}

            <!-- Renders a link tag (if your module requires any CSS)
                 <link rel="stylesheet" href="/build/app.css"> -->
        {% endblock %}

        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}

            <!-- Renders app.js & a webpack runtime.js file
                <script src="/build/runtime.js" defer></script>
                <script src="/build/app.js" defer></script>
                See note below about the "defer" attribute -->
        {% endblock %}
    </head>

    <!-- ... -->
</html>

就是这样!当您刷新页面时,来自 assets/app.js 的所有 JavaScript - 以及它包含的任何其他 JavaScript 文件 - 都将被执行。所有需要的 CSS 文件也将被显示。

encore_entry_link_tags()encore_entry_script_tags() 函数从 Encore 生成的 public/build/entrypoints.json 文件中读取,以了解要渲染的确切文件名。此文件特别有用,因为您可以启用版本控制或将 assets 指向 CDN,而无需对模板进行任何更改:entrypoints.json 中的路径将始终是最终的、正确的路径。如果您使用 splitEntryChunks()(Webpack 将输出分割成更多文件),所有必要的 scriptlink 标签都将自动渲染。

如果您不使用 Symfony,您将无法使用 encore_entry_* 函数。相反,您可以直接指向最终构建的文件,或者编写代码手动解析 entrypoints.json。只有当您使用某些可选功能(如 splitEntryChunks())时,才需要 entrypoints 文件。

1.9.0

script 标签上的 defer 属性会延迟 JavaScript 的执行,直到页面加载完成(类似于将 script 放在页面底部)。始终添加此属性的功能在 WebpackEncoreBundle 1.9.0 中引入,并在 config/packages/webpack_encore.yaml 文件中该 bundle 的 recipe 中自动启用。有关更多详细信息,请参阅 WebpackEncoreBundle 配置

引入 JavaScript 模块

Webpack 是一个模块打包器,这意味着您可以 import 其他 JavaScript 文件。首先,创建一个导出函数、类或任何其他值的文件

1
2
3
4
// assets/greet.js
export default function(name) {
    return `Yo yo ${name} - welcome to Encore!`;
};

我们将使用 jQuery 在页面上打印此消息。通过以下方式安装它

1
$ npm install jquery --save-dev

很好!使用 import 导入 jquerygreet.js

1
2
3
4
5
6
7
8
9
10
11
12
13
// assets/app.js
  // ...

+ // loads the jquery package from node_modules
+ import $ from 'jquery';

+ // import the function from greet.js (the .js extension is optional)
+ // ./ (or ../) means to look for a local file
+ import greet from './greet';

+ $(document).ready(function() {
+     $('body').prepend('<h1>'+greet('jill')+'</h1>');
+ });

就是这样!如果您之前运行了 encore dev --watch,您最终构建的文件已经更新:jQuery 和 greet.js 已自动添加到输出文件 (app.js) 中。刷新以查看消息!

Stimulus & Symfony UX

尽管上面的示例很简单,但我们建议您使用 Stimulus,而不是在 app.js 中构建您的应用程序:Stimulus 是一个小型的 JavaScript 框架,可以轻松地将行为附加到 HTML。它功能强大,您会喜欢的!Symfony 甚至提供了扩展包来为 Stimulus 添加更多功能。这些被称为 Symfony UX 扩展包。

要使用 Stimulus,首先安装 StimulusBundle

1
$ composer require symfony/stimulus-bundle

Flex recipe 应该添加几个文件/目录

  • assets/bootstrap.js - 初始化 Stimulus;
  • assets/controllers/ - 您将放置 Stimulus 控制器的目录;
  • assets/controllers.json - 帮助从您将安装的 UX 扩展包加载 Stimulus 控制器的文件。

让我们看一个简单的 Stimulus 示例。在 Twig 模板中,假设您有

1
2
3
4
5
6
7
8
9
<div {{ stimulus_controller('say-hello') }}>
    <input type="text" {{ stimulus_target('say-hello', 'name') }}>

    <button {{ stimulus_action('say-hello', 'greet') }}>
        Greet
    </button>

    <div {{ stimulus_target('say-hello', 'output') }}></div>
</div>

stimulus_controller('say-hello') 渲染一个 data-controller="say-hello" 属性。每当此元素出现在页面上时,Stimulus 将自动查找并初始化一个名为 say-hello-controller.js 的控制器。在您的 assets/controllers/ 目录中创建它

1
2
3
4
5
6
7
8
9
10
// assets/controllers/say-hello-controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
    static targets = ['name', 'output']

    greet() {
      this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!`
    }
}

结果呢?当您单击“Greet”按钮时,它会打印您的名字!如果更多 {{ stimulus_controller('say-hello') }} 元素被添加到页面 - 比如通过 Ajax - 这些元素将立即工作:无需重新初始化任何内容。

准备好了解更多关于 Stimulus 的信息了吗?

Turbo:闪电般快速的单页应用体验

Symfony 紧密集成了另一个名为 Turbo 的 JavaScript 库。Turbo 自动将所有链接点击和表单提交转换为 Ajax 调用,几乎无需更改您的 Symfony 代码!结果呢?您无需编写任何 JavaScript 即可获得单页应用程序的速度。

要了解更多信息,请查看 symfony/ux-turbo 扩展包

视频教程

或者在 SymfonyCasts 上查看 Turbo 视频教程

页面特定的 JavaScript 或 CSS

到目前为止,您只有一个最终的 JavaScript 文件:app.js。Encore 可能会为了性能而拆分成多个文件(请参阅 代码分割),但所有这些代码仍然会在每个页面上下载。

如果您有一些额外的 JavaScript 或 CSS(例如为了性能),您只想在某些页面上包含它们,该怎么办?

懒加载控制器

如果您正在使用 Stimulus,一个非常好的解决方案是利用懒加载控制器。要在控制器上激活此功能,请在您的控制器类上方添加一个特殊的 stimulusFetch: 'lazy'

1
2
3
4
5
6
7
// assets/controllers/lazy-example-controller.js
import { Controller } from '@hotwired/stimulus';

/* stimulusFetch: 'lazy' */
export default class extends Controller {
    // ...
}

就是这样!此控制器的代码 - 以及它导入的任何模块 - 将被 Encore 拆分到单独的文件中。然后,这些文件只有在匹配的元素(例如 <div data-controller="lazy-example">)出现在页面上时才会被下载!

注意

如果您使用 TypeScript 编写控制器,请确保您的 TypeScript 配置中未将 removeComments 设置为 true

多个入口

另一种选择是创建页面特定的 JavaScript 或 CSS(例如 checkout、account 等)。要处理此问题,请为每个页面创建一个新的“入口” JavaScript 文件

1
2
// assets/checkout.js
// custom code for your checkout page
1
2
// assets/account.js
// custom code for your account page

接下来,使用 addEntry() 告诉 Webpack 在构建时读取这两个新文件

1
2
3
4
5
6
7
// webpack.config.js
  Encore
      // ...
      .addEntry('app', './assets/app.js')
+     .addEntry('checkout', './assets/checkout.js')
+     .addEntry('account', './assets/account.js')
      // ...

并且由于您刚刚更改了 webpack.config.js 文件,请确保停止并重新启动 Encore

1
$ npm run watch

Webpack 现在将在您的构建目录中输出一个新的 checkout.js 文件和一个新的 account.js 文件。并且,如果这些文件中的任何一个需要/导入 CSS,Webpack 也会输出 checkout.cssaccount.css 文件。

最后,在您需要的各个页面上包含 scriptlink 标签

1
2
3
4
5
6
7
8
9
10
11
12
{# templates/.../checkout.html.twig #}
  {% extends 'base.html.twig' %}

+ {% block stylesheets %}
+     {{ parent() }}
+     {{ encore_entry_link_tags('checkout') }}
+ {% endblock %}

+ {% block javascripts %}
+     {{ parent() }}
+     {{ encore_entry_script_tags('checkout') }}
+ {% endblock %}

现在,checkout 页面将包含 app 入口的所有 JavaScript 和 CSS(因为这包含在 base.html.twig 中,并且有 {{ parent() }} 调用)以及您的 checkout 入口。通过这样做,每个页面所需的 JavaScript 和 CSS 可以放在 app 入口中,而仅 checkout 页面需要的代码可以放在 checkout 中。

使用 Sass/LESS/Stylus

您已经掌握了 Encore 的基础知识。很好!但是,如果您需要,还有许多其他功能可供您选择。例如,除了使用纯 CSS 外,您还可以使用 Sass、LESS 或 Stylus。要使用 Sass,请将 app.css 文件重命名为 app.scss 并更新 import 语句

1
2
3
// assets/app.js
- import './styles/app.css';
+ import './styles/app.scss';

然后,告诉 Encore 启用 Sass 预处理器

1
2
3
4
5
6
// webpack.config.js
  Encore
      // ...

+    .enableSassLoader()
  ;

因为您刚刚更改了 webpack.config.js 文件,所以您需要重新启动 Encore。当您这样做时,您会看到一个错误!

1
>   Error: Install sass-loader & sass to use enableSassLoader()

Encore 支持许多功能。但是,Encore 不会强制您使用所有功能,当您需要某个功能时,Encore 会告诉您需要安装什么。运行

1
2
$ npm install sass-loader@^13.0.0 sass --save-dev
$ npm run watch

您的应用现在支持 Sass。Encore 也支持 LESS 和 Stylus。请参阅 CSS 预处理器:Sass 等与 Webpack Encore

仅编译 CSS 文件

警告

支持使用 addStyleEntry(),但不建议使用。更好的选择是遵循上述模式:使用 addEntry() 指向 JavaScript 文件,然后从该文件中 require 所需的 CSS。

如果您只想编译一个 CSS 文件,可以通过 addStyleEntry() 实现

1
2
3
4
5
6
// webpack.config.js
Encore
    // ...

    .addStyleEntry('some_page', './assets/styles/some_page.css')
;

这将输出一个新的 some_page.css

继续前进!

Encore 支持更多功能!有关您可以执行的所有操作的完整列表,请参阅 Encore 的 index.js 文件。或者,返回到 前端文章列表

这项工作,包括代码示例,均根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本