Rails Asset Pipeline 资源管线(笔记)

Rails Asset Pipeline 资源管线(笔记)

 

细节小记:

# Search Paths in assets

The default locations are: app/assets/images and the subdirectories javascripts and stylesheets in all three asset locations, but these subdirectories are not special. Any path under assets/* will be searched.

也就是说,在assets目录下的任何第一层目录,都可作为搜索的目录。默认的是3个:images、stylesheets,javascripts。

 

# 除了搜索assets,其他目录也是可以配置的

Besides the standard assets/* paths, additional (fully qualified) paths can be added to the pipeline in config/application.rb. For example:

config.assets.paths << Rails.root.join("lib", "videoplayer", "flash")

 Paths are traversed in the order that they occur in the search path. By default, this means the files in app/assets take precedence, and will mask corresponding paths in lib and vendor.

 

#必须添加到precompile

It is important to note that files you want to reference outside a manifest must be added to the precompile array or they will not be available in the production environment.

 

  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
  config.assets.precompile += ['admin.css','admin.js']
 如果不这样做也可以,但是不太好。如下:

 

在production。rb文件里面,配置如下:

 

  # Don't fallback to assets pipeline if a precompiled asset is missed
  config.assets.compile = true
 

 

# Coding Links to Assets

用而且只应该用着3个:

stylesheet_link_tag 

javascript_include_tag 

image_tag 

 

# Manifest Files and Directives

不光能编译单个文件,也能够把一些文件连接在一起形成一个文件。

好处:减少请求次数

坏处:导致单个文件过大,响应时间增长;万一其中一个文件修改了,整个文件的cache将失效;

    等等,坏处很多的,注意使用啊!

 

# Using Index Files

Sprockets uses files named index (with the relevant extensions) for a special purpose.

For example, if you have a jQuery library with many modules, which is stored in lib/assets/library_name, the file lib/assets/library_name/index.js serves as the manifest for all files in this library. This file could include a list of all the required files in order, or a simple require_tree directive.

这种方法挺好了,适合有很多组件和分拆的情况。

 

#Preprocessing

For example, a stylesheet called app/assets/stylesheets/projects.css.scss.erb is first processed as ERB, then SCSS, and finally served as CSS.

很不错这种思想。

 

 

 

一、综述

    1、可以将JS和CSS合并和压缩,有写CoffeeScript、Sass和ERB的能力(可以处理这些语言的代码)

    2、在Rails的3.1版本集成了Sprockets的组件。开发人员利用这个功能可以将静态资源预执行、压缩、最小化,这是Rails默认最快策略的一部分。所以在Rails3.1版本中默认生效。当然,可以在config/application.rb的文件中更改config.assets.enabled = false禁用资源管线的功能,亦可在新建Rails工程时禁用这个功能,只在当前工程有效:rails new appname --skip-sprockets。

主要特性

    管线的首要特性是连接资源,这在生产环境中非常重要,可以快速的生成页面。在Rails3.1以上的版本中,Sprockets将所有的JS和CSS文件合并成一个 .js 和 .css 文件,在生产环境中Rails为合并后的文件名中加入 MD5 的指纹识别,这在开启缓存时非常有效。每当文件更改后,指纹识别码会更改,之前的缓存会自动失效。

    第二个是资源最小化或者压缩。执行这一过程时,CSS文件中的空格和注释、换行符会被删除;JS文件会复杂些,支持自定义的配置。

    第三个是,默认支持预编译脚本,比如:CSS的Sass,JS的CoffeeScript,适用于CSS和JS的ERB。

二、使用资源管线

    当资源管线生效时,JS和CSS资源的首选位置在app/assets下,该目录下的文件由包含在Sprockets Gem中的Sprockets中间件负责提供服务。

    在生产环境中,Rails预编译app/assets中的资源默认放到public/assets中,该目录下的文件会被当作静态资源对待,app/assets中的文件将不再使用。

    当创建控制器时,Rails会为其生成一个JS文件(若在Gemfile文件中添加coffee-rails的gem,会生成CoffeeScript文件)和一个CSS文件(若添加了sass-rails的gem,会生成SCSS文件)。例如:创建 ProjectController 后,会看到生成了app/assets/javascripts/projects.js和app/assets/stylesheets/projects.css.scss文件。在控制器对应的资源中可以加入任何独立的JS和CSS文件,因为这些资源可以通过下面的方式由控制器加载,比如:<%= javascript_include_tag params[:controller] %> 或者 <%= stylesheet_link_tag params[:contrFller] %>。

1、组织资源

    资源管线可以放在app/assets、lib/assets、vendor/assets等位置。app/assets下的资源属于应用程序,包括自定义图片,JS和CSS文件;lib/assets下的文件属于自定义类库或者共享库,不在应用程序的范畴;vendor/assets下的文件属于外部对象,比如外部JS插件和CSS框架。

    a、搜索路径

    当文件在资源清单或帮助器中引用时,Sprockets会默认搜索这三个位置。例如:

           app/assets/javascripts/home.js

           lib/assets/javascripts/movinator.js

           vendor/assets/javascripts/slider.js

    资源清单的书写方式为:

           // =require home

           // =require movinator

           // =require slider

    子文件夹下的资源也可以访问到,例如:

           app/assets/javascripts/sub/something.js

    资源清单如下:

           //= require sub/something

    这些配置可以在config/application.rb文件中找到,默认的为下面的语句:

        config.assets.paths << Rails.root.join("app", "assets", "data")

    在Rails控制台中输入 Rails.application.config.assets.paths 可以看到配置。

    注意:在资源清单外引用文件时,需将其添加到预编译数组中,否则在生产环境下不可用。预编译数组在下面会有介绍。

    b、使用索引文件

    比如,有多个模块的jQuery,存储在 lib/assets/library_name下,lib/assets/library_name/index.js文件作为所以模块的资源清单文件。这个文件中按顺序列出所有的资源。文件的内容如下:

           //= require library_name

    有了这个文件管理资源很方便。

2、编写链接资源的代码

    Sprockets不需要添加新的方法来访问资源,使用熟悉的javascript_include_tag和stylesheet_link_tag,例如:

           <%= stylesheet_link_tag "application" %>

           <%= javascript_include_tag "application" %>

    访问图片例子:

           <%= image_tag "rails.png" %>

    app/assets下面的资源由Sprockets负责提供服务。而在public/assets/下面资源,比如public/assets/rails.png由web服务器直接提供服务。Sprockets也会搜索在配置文件中指定的config.assets.paths值。图片也可以指定放在子文件夹中,使用方法如下:

           <%= image_tag "icons/rails.png" %>

    a、CSS 和 ERB

    资源管道自动处理ERB。一旦在CSS资源上加上erb的扩展名(比如:app.css.erb),那么像asset_path这样的帮助器就可以用在css中,例如:

    .class {background-image: url(<%= asset_path 'image.png' %>)}

    在资源加载时会指向 app/assets/images/image.png。若采用 data URI的方式,可以使用asset_data_uri帮助器,这会在CSS中插入图片数据,例如:

    #logo {background: url(<%= asset_data_uri 'logo.png' %>)}

    b、CSS和Sass

    使用资源管道时,定位到图片、字体、视频、音频、JS和CSS等资源的路径必须重写,并且 sass-rails 提供了 -url和 -path 帮助器,如下:

        url(/assets/rails.png) 的方式变成 image-url("rails.png")

        "/assets/rails.png" 的方式变成 image-path("rails.png")

    也可以使用更常用的方法,但是必须指定资源路径而且类型也必须要指定:

        url(/asset/rails.png) 的方式变成 asset-url("rails.png", image)

        "/assets/rails.png" 的方式变成 asset-path("rails.png", image) 

    c、JS/CoffeeScript 和 ERB

    若在JS文件后加上erb的后缀(比如:app.js.erb),那么在JS代码中就可以使用asset_path 帮助器,比如:

        $('#logo').attr({src: "<%= asset_path('logo.png') %>"});

    与之类似,在CoffeeScript文件后加上erb后缀(比如:app.js.coffee.erb),可以使用asset_path帮助器,比如:

        $('#logo').attr src: "<%= asset_path('logo.png') %>"

3、资源清单和指令

    Sprockets 使用资源清单文件,以此来决定哪些文件会被包含,并提供服务。这些文件中包含指令,Srockets可以识别哪些文件可以按顺序合并成单独的css文件和js文件。可以使用的指令包括 require和require_tree。require指令告诉Sprockets哪些文件是必须的。require_tree指令告诉Sprockets在指定的目录下所有的js文件都需要,这个路径必须是相当资源清单文件的地址。当然也可以使用require_directory,指定某个目录,但不包含递归。还有其他的指令,比如require_self等。

4、预处理

    文件的扩展名决定其是否会被预处理。使用默认的gem生成控制器时,一个CoffeeScript和一个SCSS文件会生成,比如:app/assets/javascripts/project.js.coffee和app/assets/stylesheets/project.css.scss。当请求这些文件时,coffee-script 和sass的gem包会将他们处理成对应的css和js文件。预处理可以加入其他的层,扩展名会被自右向左处理,比如:app/assets/stylesheets/projects.css.scss.erb文件,会先由ERB处理,再由SCSS处理,最后提供css。

三、开发环境

    开发模式下,资源清单中的文件会被单独显示,不会被合并成独立的文件。

1、关闭调试:

    在config/environments/development.rb文件中更改为config.assets.debug = false。当关闭调试时,Sprockets会对所有的文件进行连接并进行必要的预处理。资源清单中的文件会被合并成单独的文件。服务启动后第一次访问时,资源会被编译并缓存。Sprockets会设置 must-revalidate Cache-Control 请求头验证,以便减少服务器压力。如果在服务期间,资源清单中的文件更改,服务器会响应新的文件。

    调试模式可以内嵌到在Rails帮助器中,比如:

        <%= stylesheets_link_tag "application", :debug => true %>

        <%= javascript_include_tag "application", :debug => true %>

四、生产环境

    在生产环境中,Rails使用指纹方案。默认Rails会假设资源已经预编译并且会以静态文件的方式提供服务。

1、预编译资源

    Rails捆绑了一个 rake 命令,可以编译资源清单和资源管线中的其他文件并生成到硬盘中,默认位置为 public/assets 目录。

    在创建资源的编译版本并部署时,调用这个任务。rake任务如下:

        bundle exec rake assets:precomile

    为了更快的执行资源预编译,可以通过在config/application.rb文件中设置config.assets.initialize_on_precompile为false执行预加载应用。但在这种情况下,模版不能扫描到应用程序对象和方法。

    默认编译application.js,application.css和所有非js和css的文件(.coffee和.scss不会被自动包含进去,因为他们编译成js和css文件)

    [ Proc.new{ |path| !File.extname(path).in?(['.js', '.css']) }, /application.(css|js)$/ ]

    若有其他的资源清单或者分离的css和js文件需要包含进去,可以将他们放到预编译数组中,例如:

    config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js']

    rake 命令会生成一个 manifest.yml 的文件,包含所有的资源名称和他们对应的指纹码。典型的资源清单如下:

    ---

    rails.png: rails-bd9ad5a560b5a3a7be0808c5cd76a798.png

    jquery-ui.min.js: jquery-ui-7e33882a28fc84ad0e0e47e46cbf901c.min.js

    jquery.min.js: jquery-8a50feed8d29566738ad005e19fe1c2d.min.js

    application.js: application-3fdab497b8fb70d20cfc5495239dfc29.js

    application.css: application-8af74128f904600e41a6e39241464e03.css

    默认的资源清单在config.assets.prefix指定的路径根目录下(默认为/assets)。可以在 config.assets.manifest选项中指定绝对路径:

    config.assets.manifest = '/path/to/some/other/location'

2、服务配置

    预编译过的资源放在磁盘上并且通过web服务器提供服务。但是并不会默认设置销毁头,因此为了体现指纹的优势,需要做以下配置:

    Apache的配置:

        <LocationMatch "^/assets/.*$">

          Header unset ETag

          FileETag None

          # RFC says only cache for 1 year

          ExpiresActive On

          ExpiresDefault "access plus 1 year"

        </LocationMatch>

    Nginx的配置:

        location ~ ^/assets/ {

          expires 1y;

          add_header Cache-Control public;

          add_header ETag "";

          break;

        }

    Sprockets会创建资源的gzip压缩版本。web服务器的典型配置是使用中度压缩,但是由于已经进行了预编译,Sprocket会使用最大的压缩率,因此减少了数据传输量。另一方面,web服务器可配置成从硬盘中获取压缩好的内容直接提供服务。Nginx的配置如下:

        location ~ ^/(assets)/  {

          root /path/to/public;

          gzip_static on; # to serve pre-gzipped version

          expires max;

          add_header Cache-Control public;

        }

3、及时编译(Live Compilation)

    某些情况下,需要使用及时编译模式。在这个模式中所有的资源的请求都由Sprockets直接处理,可以通过下面的语句开启:

        config.assets.compile = true

    第一次请求时资源会被编译并缓存,而且在帮助器中使用的资源名称也会加上 MD5的标识。Sprockets会为这些资源加上 Cache-Control 的HTTP头,其中max-age=31536000

    这种模式会消耗更多的内存,性能较差,不推荐使用。

    若部署生产应用时不存在任何的JavaScript运行时,会出错,需要在Gemfile文件中加入以下引用:

        group :production do

          gem 'therubyracer'

        end

五、自定义管线

1、CSS 压缩

    有一个可选的CSS压缩工具 YUI。启用YUI压缩如下:

        config.assets.css_compressor = :yui

        config.assets.compress = true

    需要添加 yui-compressor 的gem。

2、JS压缩

    JS压缩工具有 closure,uglifier,yui,他们对应的gem如下:closure-compiler,uglifier,yui-compressor。Ruby默认的压缩是uglifier。

3、使用自己的压缩工具

    CSS和JS的的压缩配置需要定义一个对象,并且对应必须存在 compress的方法,该方法有个字符串参数,必须返回一个字符串,范例如下:

        class Transformer

          def compress(string)

            do_something_returning_a_string(string)

          end

        end

    在application.rb中按下面的方式修改,会使配置生效:

        config.assets.css_compressor = Transformer.new

4、改变 assets 的路径

    Sprockets的默认公共路径为 /assets。更改路径的设置为:

        config.assets.prefix = "/some_other_path"

    这在已经存在的工程中,使用新的资源的路径时很有用。

5、X-Sendfile Headers

    X-Sendfile 头表示指向web服务器忽略应用的响应,并从磁盘上直接提供文件服务。这个功能默认关闭。如果打开,文件服务会更快。Apache和Nginx支持这个配置:

        config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache

        config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

 

 

From:http://hi.baidu.com/superwanderman/item/51942441fe1037fedd0f6cce

 

+

+

+

-

+

+

+

 

 

你可能感兴趣的:(pipeline)