如何最小化CSS/JS文件(使用UglifyJS和UglifyCSS)

3.4 版本
维护中的版本

从Symfony 2.8开始,Assetic已不再是Symofny标准版框架的自带内容。参考 这篇文章 以了解如何在你的程序中安装和开启Assetic。

UglifyJS 是一个JavaScript解析器/压缩器/美化器的工具包。它可以用于合并和最小化JS资源,以便使其占用更少的HTTP请求,同时令你的网站加载更快。UglifyCSS 是一个CSS压缩器/美化器,很像UglifyJS。

本文,会对UglifyJS的安装、配置和用法进行详细解释。UglifyCSS 的工作方式高度类似,故只做简要介绍。

安装UglifyJS 

UglifyJS可以作为 Node.js 的一个模块来使用。首先,你要 安装Node.js,然后要决定安装方式:全局还是本地。

全局安装 

全局安装方式让你的项目使用完全相同的UglifyJS版本,可以简化维护。打开命令行工具,执行以下命令(你需要使用root/administrator权限的用户):

1
$  npm install -g uglify-js

现在你可以在系统的任何地方来执行全局 uglifyjs 命令:

1
$  uglifyjs --help

本地安装 

也可以只在项目里面安装UglifyJS,这在你的项目需要一个特定版本的UglifyJS时有用。要这样做,安装时不要使用 -g 选项,并指定你要把模块安装到哪个路径下:

1
2
$  cd /path/to/your/symfony/project
$  npm install uglify-js --prefix app/Resources

推荐你把UglifyJS安装到 app/Resources 文件夹,然后添加一个 node_modules 目录用于版本控制。另有可选方案,你可以创建一个npm package.json文件,用于指定你的依赖。

现在你可以在 node_modules 目录下去可以执行 uglifyjs 命令了:

1
$  "./app/Resources/node_modules/.bin/uglifyjs" --help

配置UglifyJS2的filter 

现在你可以配置Symfony,在处理JavaScripts时使用 uglifyjs2 过滤器了:

1
2
3
4
5
6
7
# app/config/config.yml
assetic:
filters:
uglifyjs2:
# the path to the uglifyjs executable
# 可执行uglifyjs的路径
bin: /usr/local/bin/uglifyjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:assetic="http://symfony.com/schema/dic/assetic"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/assetic
        http://symfony.com/schema/dic/assetic/assetic-1.0.xsd">
 
    <assetic:config>
        <!-- bin: the path to the uglifyjs executable -->
        <assetic:filter
                name="uglifyjs2"
                bin="/usr/local/bin/uglifyjs" />
    </assetic:config>
</container>
1
2
3
4
5
6
7
8
9
// app/config/config.php
$container->loadFromExtension('assetic', array(
'filters' => array(
'uglifyjs2' => array(
// the path to the uglifyjs executable
'bin' => '/usr/local/bin/uglifyjs',
),
),
));

UglifyJS的安装路径,根据系统的不同可以多种多样。要找到哪里才是npm存储 bin 文件夹的地方,执行以下命令:

1
$  npm bin -g

这时应该会输出一个系统中的文件夹,你可以在里面找到可执行的UglifyJS。

如果你是本地安装UglifyJS,可以在 node_modules 文件夹中找到 bin 目录。本例中它被命名为 .bin

现在你可以在程序中访问到 uglifyjs2 了。

配置node Binary 

Assetic会尝试自动找到node二进制文件。如果找不到,你可以配置它的位置,使用 node 键:

1
2
3
4
5
6
7
8
9
10
# app/config/config.yml
assetic:
# the path to the node executable
# 可执行node的路径
node: /usr/bin/nodejs
filters:
uglifyjs2:
# the path to the uglifyjs executable
# 可执行uglifyjs的路径
bin: /usr/local/bin/uglifyjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:assetic="http://symfony.com/schema/dic/assetic"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/assetic
        http://symfony.com/schema/dic/assetic/assetic-1.0.xsd">
 
    <assetic:config
            node="/usr/bin/nodejs" >
        <assetic:filter
                name="uglifyjs2"
                bin="/usr/local/bin/uglifyjs" />
    </assetic:config>
</container>
1
2
3
4
5
6
7
8
// app/config/config.php
$container->loadFromExtension('assetic', array(
'node' => '/usr/bin/nodejs',
'uglifyjs2' => array(
// the path to the uglifyjs executable
'bin' => '/usr/local/bin/uglifyjs',
),
));

最小化你的资源 

为了在你的assets资源上使用UglifyJS,在你模板的asset标签中添加 filter 选项,来告诉Assetic使用 uglifyjs2 过滤器(filter):

1
2
3
{% javascripts '@AppBundle/Resources/public/js/*' filter='uglifyjs2' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
1
2
3
4
5
6
<?php foreach ($view['assetic']->javascripts(
array('@AppBundle/Resources/public/js/*'),
array('uglifyj2s')
) as $url): ?>
<script src="<?php echo $view->escape($url) ?>"></script>
<?php endforeach ?>

上例假设你有一个名为AppBundle的bundle,你的JavaScript文件位于该bundle的 Resources/public/js 目录下。然而你也可以包容任意位置的JS文件。

在asset标签里添加了上面的 uglifyjs2 过滤器之后,你应该可以看到最小化的Javascripts加载得很快。

在Debug Mode中禁止最小化 

最小化的JavaScript文件难以阅读,但调试时除外。因此,Assetic允许你在程序的debug模式下(如, app_dev.php)关闭一个特定的filter。你可以在模板中,用一个问号: ? 来对过滤器的名称添加前缀。这就告诉Assetic仅在debug模式关闭时才应用此过滤(如 app.php 时):

1
2
3
{% javascripts '@AppBundle/Resources/public/js/*' filter='?uglifyjs2' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
1
2
3
4
5
6
<?php foreach ($view['assetic']->javascripts(
array('@AppBundle/Resources/public/js/*'),
array('?uglifyjs2')
) as $url): ?>
<script src="<?php echo $view->escape($url) ?>"></script>
<?php endforeach ?>

要测试一番,切换你的 prod 环境(app.php)。但是在这之前,别忘了 清除你的缓存 以及 剥离Assetic资源

除了在asset标签中添加filter之外,你也可以在程序级配置文件中,对“为每个资源文件使用哪个过滤器”进行配置。参考 基于文件扩展名过滤 以了解更多。

安装、配置和使用UglifyCSS  

UglifyCSS的工作方式与UglifyJS相同。首先,确保node环境已经安装:

1
2
3
4
5
6
# global installation / 全局安装时
$  npm install -g uglifycss
 
# local installation / 本地安装时
$  cd /path/to/your/symfony/project
$  npm install uglifycss --prefix app/Resources

接下来,为filter添加配置信息:

1
2
3
4
5
# app/config/config.yml
assetic:
filters:
uglifycss:
bin: /usr/local/bin/uglifycss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:assetic="http://symfony.com/schema/dic/assetic"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/assetic
        http://symfony.com/schema/dic/assetic/assetic-1.0.xsd">
 
    <assetic:config>
        <assetic:filter
                name="uglifycss"
                bin="/usr/local/bin/uglifycss" />
    </assetic:config>
</container>
1
2
3
4
5
6
7
8
// app/config/config.php
$container->loadFromExtension('assetic', array(
'filters' => array(
'uglifycss' => array(
'bin' => '/usr/local/bin/uglifycss',
),
),
));

要对css文件使用这个过滤器,为Assetic的 stylesheets helper添加filter:

1
2
3
{% stylesheets 'bundles/App/css/*' filter='uglifycss' filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
1
2
3
4
5
6
7
<?php foreach ($view['assetic']->stylesheets(
array('bundles/App/css/*'),
array('uglifycss'),
array('cssrewrite')
) as $url): ?>
<link rel="stylesheet" href="<?php echo $view->escape($url) ?>" />
<?php endforeach ?>

就像 uglifyjs2 这个过滤器一样,如果你对过滤器名称添加一个 ?(如,?uglifycss),则最小化仅发生在你没有处于debug模式的时候。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)