Pull to refresh

Сжатие javascript средствами packr

Reading time4 min
Views952
У многих веб разработчиков рано или поздно встает вопрос об ускорении загрузки своих сайтов. Это связано с тем, что не у всех есть мегабитные каналы, и некоторые пользователи все еще сидят на dialup. В данной статье я опишу как сжимать яваскрипты дла production, объединять их в один файл, так же дальнейшие улучшения. Предположим у нас есть набор скриптов: swfobject.js, jquery-1.3.2.js, jquery.media.js, jquery.markitup.js, jquery.markitup.set.js, application.js. Их размер порядка 150 КБ, упаковщик позволит сжать их до 50 КБ.

Раньше я пользовался asset_packager, но его возможности скромны, он просто удаляет комментарии, лишние пробелы и переносы строк в файлах яваскриптов и css. Поэтому я стал искать другой способ. Предлагаю вам свое решение.


Установка гема packr

Добавляем в файл config/environment.rb строчку
config.gem 'packr':lib => false

и выполняем sudo rake gems:install

Создание списка файлов скриптов

Создадим config/js_files.yml, имеющий содержание обычного ямл файла:

base:
  - swfobject.js
  - jquery-1.3.2.js
  - jquery.media.js
  - jquery.markitup.js
  - jquery.markitup.set.js
  - application.js


Инициализация файлов

Чтобы полчить список файлов, создадим файл initializers/javascript_files.rb

JAVASCRIPT_FILES = YAML::load( File.read("#{RAILS_ROOT}/config/js_files.yml") ).symbolize_keys
 
if RAILS_ENV == "production"
  JAVASCRIPT_FILES_PACKED = Proc.new{prod_files = {} ; JAVASCRIPT_FILES.each { |key , value| prod_files[key] = value.map{|v| "packed/" + v} } ; prod_files }.call
  ActionView::Helpers::AssetTagHelper.register_javascript_expansion JAVASCRIPT_FILES_PACKED
else
   ActionView::Helpers::AssetTagHelper.register_javascript_expansion JAVASCRIPT_FILES
end


Из этого кода видно что пути для яваскриптов в продакшне изменяются на подпапку «packed».
ActionView::Helpers::AssetTagHelper.register_javascript_expansion JAVASCRIPT_FILES 
— позволит подключать хелпером javascript_include_tag несколько файлов по ключам которые указаны в js_files.yml.

Добавление яваскриптов в шаблон

javascript_include_tag :base:cache => "base_packed"


:cache, когда установлено config.action_controller.perform_caching = true будет выдавать нам один файл base_packed.js, содержанием которого будут все файлы перечисленные в :base.

Task для упаковки

Создаем файл lib/tasks/packr.rake

require 'packr'
 
namespace :packr do
  task :pack do
    files = YAML::load( File.read("#{RAILS_ROOT}/config/js_files.yml") )["base"]
    files.each do |file|
      puts "#{file} packing..."
      File.open("#{RAILS_ROOT}/public/javascripts/packed/#{file}"'wb') do |f|
        f.write(Packr.pack(File.read("#{RAILS_ROOT}/public/javascripts/#{file}"):shrink_vars => true:private => true:base62 => true))
      end
      puts "packed\n\n"
    end
  end
end


Сразу несколько слов об этом коде, тут в данном случае будут запакованы только файлы с ключем «base» и сложены в папку «javascripts/packed», к этом я вернусь в конце статьи.

Итак, все готово к упаковке. Но перед этим надо создать папку «javascripts/packed», иначе получите ошибку.

Чтобы запустить упаковщик выполните команду rake packr:pack. Упакованные файлы вы найдете в созданной заренее «javascripts/packed».

Дальнейшие улучшения


Первое:

В скриптах указана папка для упакованных файлов, задана она в каждом скрипте. Для универсальности следует вынести ее в константу.

Второе:

В таске запаковываются файлы только из ключа :base, здесь следует убрать этот параметр из строчки
files = YAML::load( File.read("#{RAILS_ROOT}/config/js_files.yml") )["base"]
и сделать проходы по всем ключам. При необходимости добавить параметр какой именно ключ необходимо паковать.

Третье:

Файлы исходников яваскриптов находятся по прежнему в папе «public/javascripts», нужно переместить их, например, в «lib/javascripts», т.к. в продакшне они там ни к чему. В девелопменте можно просто делать ссылку из lib в public. В продакшне в «public/javascripts» складывать запакованные файлы, и папка «packed» будет не нужна. При этом упростится и скрипт initializers/javascript_files.rb, т.к. не нужно будет делить файлы на продакшн и девелопмент.

Четвертое:

Файлы надо упаковывать на сервере, перед перезапуском сервера. Если вы используете capistrano то можно делать, например, следующим образом:

task :before_symlink do
  run "mkdir -p #{release_path}/public/javascripts"
  run "rake packr:pack"
end


Предложения и замечания приветствуются.
Спасибо за внимание!
Tags:
Hubs:
Total votes 5: ↑3 and ↓2+1
Comments24

Articles