maba / webpack-bundle
将Webpack集成到Symfony的项目中
Requires
- php: ^5.5 || >=7.0
- maba/dependency-injection-extra: ^0.1.1|^1.0
- symfony/console: ^2.5|^3.0|^4.0
- symfony/dependency-injection: ^2.6|^3.0|^4.0
- symfony/framework-bundle: ^2.7|^3.0|^4.0
- symfony/monolog-bundle: ^2.3|^3.0|^4.0
- symfony/process: ^2.5|^3.0|^4.0
- symfony/routing: ^2.7|^3.0|^4.0
- symfony/templating: ^2.1|^3.0|^4.0
- symfony/twig-bundle: ^2.3|^3.0|^4.0
- twig/twig: ^1.27|^2.0
Requires (Dev)
- codeception/codeception: ~2.3@dev
- doctrine/annotations: ^1.0
- doctrine/cache: ^1.5
- friendsofphp/php-cs-fixer: ^2.2
- symfony/asset: ^2.7|^3.0|^4.0
- symfony/framework-bundle: ^2.7.1|^3.0|^4.0
- symfony/translation: ^2.7|^3.0|^4.0
README
Symfony扩展,帮助将webpack集成到Symfony项目中。
什么是webpack?
模块打包器和CommonJS/AMD依赖管理器。
对我来说,它取代了grunt/gulp和RequireJS。
这个扩展做了什么?
- 在twig模板中找到javascript入口点。
- 使用assets-webpack-plugin运行webpack。
- 保存生成的文件名,以便twig函数返回正确的资源URL。
此外,在开发环境中
- 运行webpack-dev-server,当资源发生变化时,它会提供并重新生成资源。
- 监视twig模板的更改,当webpack配置发生变化时,更新入口点并重启webpack-dev-server。
更多功能
- 允许您按需配置webpack配置,同时仍然提供来自Symfony的所需参数,如入口点、别名、环境和附加参数。
- 允许您定义自定义入口点提供者,如果您不使用twig或以其他方式包含脚本。
- 默认支持图像和css/less/sass文件,如有需要。
- 支持Webpack 2(默认)和Webpack 1。
请查看Symfony、Webpack和AngularJS单页面应用示例以获取使用示例。
还可以查看MabaWebpackMigrationBundle,它可以帮助从AsseticBundle迁移到webpack。
这与assetic相比如何?
Webpack允许您创建知道其依赖项的组件。
使用assetic时,您必须显式地在模板中提供所有需要的javascript和CSS文件。如果您将一个javascript文件分割成两个文件,您需要更新所有需要新依赖项的模板。使用webpack,您只需在javascript文件中用require('./newFile.js');
即可。
此外,您可以通过javascript像其他javascript一样轻松地require CSS文件 - require('./styles.css');
然后您就可以开始了。
如果您的应用程序是前端驱动的,迟早您需要异步加载您的资源。Webpack默认支持这一点。Assetic仅打包资源,您需要使用类似RequireJS的库来完成此操作(例如,您可以考虑HearsayRequireJSBundle作为替代方案)。
webpack-dev-server支持文件的即时重新加载,有时无需刷新页面(对于样式和一些JS框架,如React来说非常理想)。
安装
composer require maba/webpack-bundle
在AppKernel
内部
new Maba\Bundle\WebpackBundle\MabaWebpackBundle(),
运行命令
app/console maba:webpack:setup
它会复制默认的webpack.config.js
和package.json
文件,并运行npm install
。
如果任何文件已存在,您将被询问是否要覆盖它们。
webpack.config.js
必须导出一个函数,该函数接受options
作为参数,并返回webpack配置。
您可以根据需要修改此配置文件 - 扩展仅提供默认配置作为起点。
您应该将 webpack.config.js
和 package.json
添加到您的仓库中。您还应该将 node_modules
添加到 .gitignore
文件中,并运行 npm install
,类似于 composer install
(在克隆仓库后,在 package.json
更新后,以及在部署任务中)。当然,您也可以直接将其添加到您的仓库中。
git add package.json app/config/webpack.config.js
如果您出于某种原因想使用 Webpack 1,请将 --useWebpack1
作为命令行选项传递给 setup
命令。
用法
在 twig 模板内部
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> {% webpack css '@app/bootstrap.less' '@ApplicationBundle/Resources/assets/script.js' %} <link rel="stylesheet" href="{{ asset_url }}"/> {% end_webpack %} </head> <body> <img src="{{ webpack_asset('@app/funny-kitten.png') }}"/> <script src="{{ webpack_asset('@ApplicationBundle/Resources/assets/script.js') }}"></script> </body> </html>
在 script.js
内部
require('./script2.js'); require('./my-styles.less'); function loadScript3() { require.ensure([], function() { require('@AnotherBundle/Resources/assets/script3.js'); require('./style.css'); }); } setTimeout(loadScript3, 1000);
作为部署到生产环境的一部分,在清除缓存之后
app/console maba:webpack:compile --env=prod
在开发环境中(这必须始终在后台运行,类似于 assetic:watch
)
app/console maba:webpack:dev-server
或者,如果您不是积极开发您的前端,您可以一次性编译并忘记它,类似于生产环境
app/console maba:webpack:compile
如果您正在对您的应用程序运行功能测试,请确保为测试环境编译一次以生成测试环境的清单文件
app/console maba:webpack:compile --env=test
Twig 函数和标签
您可以选择使用 webpack_asset
函数或 webpack
标签。
函数
webpack_asset(resource, type = null)
type
是 js
或 css
,留空以猜测类型。对于 css
,此函数可能会返回 null
,如果从提供的入口点提取不出 CSS。如果您确定将有一些 CSS,您可以忽略这一点。否则,您可以使用 webpack
标签,因为它为您处理这一点(在这种情况下,完全省略了 <link/>
标签)。
标签
{% webpack [js|css] [named] [group=...] resource [resource, ...] %} Content that will be repeated for each compiled resource. {{ asset_url }} - inside this block this variable holds generated URL for current resource {% end_webpack %}
与 webpack_asset
函数类似,提供 js
、css
或留空以猜测类型。
在 使用通用块 部分中查看使用 named
和 group
的示例。
请注意,您必须在标签和函数中提供硬编码的资产路径。这是为了在编译时找到所有可用的资产。
样式表
默认情况下,已配置 ExtractTextPlugin。这意味着如果您 require
任何编译为 CSS(.css
、.less
、.scss
)的文件,它将从编译的 JS 文件中删除并存储在单独的文件中。因此,您必须显式包含它。
请注意,当您提供入口点时,它通常仍然是 .js
文件(请参阅使用示例)。
如果您想禁用此功能,以便 CSS 与 JS 一起在单个请求中加载,请禁用 extract_css
maba_webpack: config: parameters: extract_css: false
如果您想直接将 css/less/sass 文件作为入口点,则需要此插件。
ES6、Less 和 Sass 支持
ES6、Less 和 Sass 无需配置即可使用
如果您需要任何自定义加载器,请随时使用 npm
安装它们,并在必要时修改 app/config/webpack.config.js
。
加载图像
默认情况下,使用 image-webpack-loader 对图像进行优化。
您可以使用相同的 webpack_asset
函数直接在 twig 模板中包含图像。
为了正确运行,图像文件的加载器必须保持您的 webpack 配置中的 file
。
<img src="{{ webpack_asset('@AcmeHelloBundle/Resources/images/cat.png') }}"/>
当然,您也可以在 CSS 中使用它们。
.cat { /* cat.png will be optimized and copied to compiled directory with hashed file name */ /* URL to generated image file will be in the css output */ background: url("~@AcmeHelloBundle/Resources/images/cat.png") }
如果您在 CSS 中提供 webpack 兼容的资产路径,请用 ~
前缀。使用相对路径,如常。有关更多信息,请参阅 css-loader。
别名
默认情况下,别名前缀为 @
,指向特定的路径。您可以通过配置 aliases.prefix
参数来更改此前缀。
别名在 twig 模板(webpack_asset
函数的参数)和 JavaScript 文件(require
或类似 Webpack 提供的函数)中工作方式相同。
默认情况下,这些别名已注册
@app
,指向%kernel.root_dir%/Resources/assets
@root
,指向%kernel.project_dir%
(通常是您的仓库根目录)@templates
,指向%kernel.project_dir%/templates
@assets
,指向%kernel.project_dir%/assets
@AcmeHelloBundle
或类似为每个您的包。这指向包的根目录(Bundle
类所在的目录),与在 Symfony 中定位资源时相同@acme_hello
或类似为每个您的包。默认情况下,这指向@AcmeHelloBundle/Resources/assets
您也可以注册自己的别名,例如如果您使用任何这些包管理器,则 @bower
或 @npm
是不错的选择。或者如果您使用 composer 安装前端资源,则类似 @vendor
也很合适。
maba_webpack: aliases: additional: npm: %kernel.root_dir%/node_modules # or any other path where assets are installed bower: %kernel.root_dir%/bower vendor: %kernel.root_dir%/../vendor
在您的 JavaScript 文件内
var $ = require('@npm/jquery');
如果您想使用不同的前缀
maba_webpack: aliases: prefix: '%' additional: npm: %kernel.root_dir%/node_modules
现在在您的 JavaScript 文件内
var $ = require('%npm/jquery');
请确保在无法直接从网络上访问的路径上安装依赖项(无论是 npm、bower 还是其他)。Webpack 不需要这(它会编译它们 - 它们可以位于系统上的任何位置),并且可能导致安全漏洞(某些资源包含后端示例,这可能在您的生产环境中被潜在使用)。
配置
请参阅带解释的示例。
maba_webpack: enabled_bundles: - ApplicationBundle twig: additional_directories: - %kernel.root_dir%/Resources/partials suppress_errors: true # whether files not found or twig parse errors should be ignored # defaults to true in dev environment # defaults to "ignore_unkwowns" in prod - this option ignores # unknown functions etc., but fails on syntax errors # set to false to always fail on any twig error config: path: '%kernel.root_dir%/config/webpack.config.js' parameters: [] # additional parameters passed to webpack config file # for example, set dev_server_public_path and public_path to overwrite # //:8080/compiled/ and /compiled/ # see inside your webpack.config.js for more info # set location of cached manifests. Useful for deploy, when you don't want to include your cache directory manifest_file_path: '%kernel.cache_dir%/webpack_manifest.php' aliases: # allows to set aliases inside require() in your JS files path_in_bundle: /Resources/assets # this means that require('@acme_hello/a.js') # will include something like # src/Acme/Bundles/AcmeHelloBundle/Resources/assets/a.js # see "Aliases" for more information prefix: '@' # configure default prefix to be added to aliases. additional: [] # provide any other aliases, prefix is always added automatically bin: webpack: executable: # how maba:webpack:compile executes webpack # should be array, for example ['/usr/bin/node', 'node_modules/webpack/bin/webpack.js'] - node_modules/.bin/webpack arguments: [] # additional parameters to pass to webpack # --config with configuration path is always passed dev_server: executable: # how maba:webpack:dev-server executes webpack-dev-server - node_modules/.bin/webpack-dev-server arguments: # additional parameters to pass to webpack-dev-server; these are default ones - --hot - --history-api-fallback - --inline disable_tty: false # disables TTY setting. Defaults to false in dev environment, true in others. # TTY is needed to run dashboard and/or to display colors, but does not work # in some environments like AWS working_directory: %kernel.root_dir%/.. dashboard: # configuration for dashboard plugin - only works when TTY available enabled: dev_server # `always` for both compile and dev-server, `false` to disable executable: - node_modules/.bin/webpack-dashboard
配置 dev-server
app/console maba:webpack:dev-server
以独立进程运行 webpack-dev-server,它监听在 localhost:8080
。默认情况下,开发环境中的资源指向 //:8080/compiled/*
。
如果您在 VM、docker 容器等内部运行此命令,请配置 maba_webpack.config.parameters.dev_server_public_path
以使用正确的宿主。此外,由于 dev-server 默认只监听 localhost 连接,请将以下内容添加到配置中
maba_webpack: bin: dev_server: arguments: - --hot # these are default options - leave them if needed - --history-api-fallback - --inline - --host # let's add host option - 0.0.0.0 # each line is escaped, so option comes in it's own line - --public # this is also needed from webpack-dev-server 2.4.3 - dev-server-host.dev:8080 # change to whatever host you are using config: parameters: # this is where the assets will be loaded from dev_server_public_path: //dev-server-host.dev:8080/compiled/ dev_server: {} # any additional parameters to pass to `devServer` configuration
如果您需要提供不同的端口,请确保将 --port
和端口号本身放在单独的行上。
当使用 webpack-dev-server
编译资源时,使用 webpack-dashboard 以获得更友好的用户体验。您可以通过将 tty_prefix
选项设置为 []
来禁用它。您还可以在这种情况下从 webpack.config.js
中删除 DashboardPlugin
。
配置 Node.js 的内存
如果您在运行 maba:webpack:compile
和/或 maba:webpack:dev-server
时遇到“堆内存不足”错误,请尝试为 Node.js 进程提供更多内存。
maba_webpack: bin: webpack: # same with dev_server executable: - node - "--max-old-space-size=4096" # 4GB - node_modules/webpack/bin/webpack.js
使用公共块
此包支持单个和多个 公共块,但您必须明确配置此功能。
在您的 webpack.config.js
config.plugins.push( new webpack.optimize.CommonsChunkPlugin({ name: 'commons' }) );
在您的基模板中
{% webpack named css 'commons' %} <link rel="stylesheet" href="{{ asset_url }}"/> {% end_webpack %} {# ... #} {% webpack named js 'commons' %} <script src="{{ asset_url }}"></script> {% end_webpack %}
您也可以使用 webpack_named_asset
twig 函数来替代 webpack
标签。
分组公共块
webpack
标签支持 group
选项
{% webpack js '@app/admin-init.js' group='admin' %} <script src="{{ asset_url }}"></script> {% end_webpack %}
资源名称在 options.groups
中给出,它传递到您的 webpack.config.js
。未设置组的资源被分配到 default
组。配置示例
config.plugins.push(new webpack.optimize.CommonsChunkPlugin({ name: 'admin_commons_chunk', chunks: options.groups['admin'] })); config.plugins.push(new webpack.optimize.CommonsChunkPlugin({ name: 'front_commons_chunk', chunks: options.groups['default'] }));
请注意,目前同一个入口点不能属于多个组,即使它在不同的地方使用。这意味着您必须为同一资源的 JavaScript 和 CSS 版本提供相同的组。
关于包继承的说明
如果您使用具有继承的包,请注意,这些资源本身通常在不同的上下文中解析(在webpack本身中),指向父包(通过其别名)的资源实际上会指向子包。这允许您覆盖父包中的任何资源,但需要复制所有资源,因为它们根本不会在父包目录中查找。
语义化版本控制
此包遵循语义化版本控制。
此包的公共API(换句话说,如果您想轻松更新到新版本,则应仅使用这些功能)
- 只有未标记为
public="false"
的服务 - 只有标记有
@api
的类、接口和类方法 - twig函数和标签
- 控制台命令
- 支持的DIC标签
例如,如果只有类方法标记为@api
,则不应扩展该类,因为构造函数可能在任何版本中更改。
有关API中可以更改和不能更改的基本信息,请参阅Symfony BC规则。请注意,在此包中,默认情况下所有内容都是@internal
。
更新此包后,您应重新运行maba:webpack:setup
命令并审查文件中的更改,将它们合并到您自己的文件中。此包可能假设已安装所有所需的依赖项。由于编译是在部署步骤之前进行的,因此您应注意到在预发布环境中可能出现的任何错误。
替代方案?
有几种方法可以集成webpack。
简单的webpack命令
我强烈建议这种方法 - 仅将前端代码(HTML、CSS、JS)与后端代码(PHP + 一些HTTP API)分开。
特别是如果您有单页应用程序,将webpack工作流程与Symfony集成几乎没有意义。
在这种情况下,您可以使用html-webpack-plugin生成包含正确URL的HTML文件,以便指向打包的javascript文件。
ju1ius/WebpackAssetsBundle
这是一个最小的包,用于将编译后的文件名提供给您的twig模板。它还使用了assets-webpack-plugin。
与此包相比缺少的功能 - 收集所有入口点。您必须手动在webpack配置中设置它们。如果只有少数几个,通常不难维护。
Webpack配置完全是手动的,并且不与您的Symfony应用程序集成。
hostnet/webpack-bundle
此包收集所有入口点,但不会提供用于在twig模板中使用的生成URL。它通过添加修改时间戳来解决缓存失效问题。
Webpack配置完全集成到您的Symfony应用程序中,并且需要自定义PHP代码进行任何自定义配置更改。
在开发环境中,它在请求时生成资产。这可能比在后台运行特定命令更方便,但通常速度较慢。此外,此时很难将其与webpack-dev-server集成。
它有更多的twig标签,如内联脚本。一个例子是内联splitpoint生成,它允许您为每个文件生成简单的splitpoints。
运行测试
composer install vendor/bin/codecept run