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.js
和 app.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
所有这些命令 - 例如 dev
或 watch
- 都是在您的 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 将输出分割成更多文件),所有必要的 script
和 link
标签都将自动渲染。
如果您不使用 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
导入 jquery
和 greet.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 的信息了吗?
- 阅读 Stimulus 文档
- 了解更多关于 StimulusBundle & UX 系统的信息
-
视频教程
Turbo:闪电般快速的单页应用体验
Symfony 紧密集成了另一个名为 Turbo 的 JavaScript 库。Turbo 自动将所有链接点击和表单提交转换为 Ajax 调用,几乎无需更改您的 Symfony 代码!结果呢?您无需编写任何 JavaScript 即可获得单页应用程序的速度。
要了解更多信息,请查看 symfony/ux-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.css
和 account.css
文件。
最后,在您需要的各个页面上包含 script
和 link
标签
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 文件。或者,返回到 前端文章列表。