Skip to content

Импорт статических сайтов в структуру другого сайта

Notifications You must be signed in to change notification settings

sergeche/site-import

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Импорт статических сайтов Build Status

Механизм импорта статических сайтов в структуру другого сайта: копирует файлы из внешнего сайта в указанную папку текущего сайта таким образом, чтобы этот внешний сайт стал частью текущего, с правильной навигацией между страницами и ссылками на ресурсы.

Возможности

  • Автоматическая перезапись абсолютных и относительных ссылок на страницы и файлы внутри HTML и CSS.
  • При перезаписи ссылок на ресурсы сайта (графика, CSS, JS и т.д.) можно получать мета-информацию о файле и использовать её для генерации ссылок со сбросом кэша. Например, использовать CRC32 от содержимого файла или дату последней модификации.
  • Файлы, в которых не меняется содержимое при импорте (графика, JS) можно как копировать, так и ставить симлинки для снижения общего веса сайта.
  • Очень гибкий механизм для добавления своих преобразований ресурсов подсайта для получения нужного результата.

Основные концепции

Для успешного импорта подсайта нужно знать следующие вещи:

  • папка, откуда копировать подсайт;
  • папка, куда копировать подсайт;
  • префикс, который нужно добавить всем ссылкам внутри подсайта, чтобы правильно работала навигация в подсайте в контексте целевого сайта.

Пример

Есть сайт mini-site со следующей стркутурой:

  • /index.html
  • /help/index.html
  • /img/**
  • /css/**

И мы хотим, чтобы этот mini-site стал частью сайта global-site и был доступен по адресу http://global-site.com/company/about/.

Для этого нам нужно:

  • перенести файлы из папки /path/to/mini-site в папку /path/to/global-site/www/company/about;
  • во время переноса заменить ссылки внутри mini-site. Например, ссылка /help/ должна превратиться в ссылку /company/about/help/, то есть нужно добавить префикс /company/about.

Чтобы не придумывать отдельный конфиг для указания этой информации, в импорте есть специальный механизм для получения всей необходимой информации на основе файловой стркутуры. Для этого достаточно сделать специальную папку, в которой симлинками разметить импортируемые разделы. Например:

/path/to/global-site/import
    /company
        /about -> /path/to/mini-site

TODO: написать подробнее про файловую структуру (если кому-то будем предоставлять этот инструмент). Сейчас про разметку импорта симлинками все знают.

Как это работает

Импорт сайтов активно использует Node Streams, которые не только позволяют снизить нагрузку и увеличить скорость работы импорта, но и предоставляют удобные механизмы для добавления новых механизмов трансформации файлов, необходимых для конкретного проекта.

Основной единицей потока импорта является проект. Проект — это объект, который содержит информацию об импортируемом сайте (mini-site в примере выше): путь к папке с проектом, префикс и т.д.

Когда проект переходит в стадию фактического переноса данных из одной папки в другую (в терминах Node Streams: пишем данные в writable stream), он начинает считывать все файлы сайта и применять к ним различные трансформации.

Концепция работы очень похожа на то, как работает Gulp: из папки считываются файлы, которые затем как-то преобразуются и сохраняются в другую папку. Файлы можно не только преобразовывать, но и создавать новые или убирать из потока ненужные. Всё то же самое можно делать и в импорте сайтов, только оперировать нужно двумя единицами данных: проект и файл проекта.

Пример:

var si = require('site-import');
var through = require('through2');

// считываем структуру импортируемых сайтов
si.src('/path/to/global-site/import')
.pipe(through.obj(function(project, enc, next) {
    // Делаем различные манипуляции с проектом.
    // Переменная `project` – экземпляр класса `ProjectConfig`, 
    // см. lib/project-config.js
    
    // ...
    
    // Передаём его дальше в импорт. Если проект нужно игнорировать,
    // то метод push() не вызываем.
    this.push(project);

    // Переходим к следующему проекту. Этот метод нужно вызывать ВСЕГДА,
    // когда закончились преобразования над текущим объектом.
    next();
}))
// сохраняем сайты в указанную папку
.pipe(si.dest('/path/to/global-site/www'))
.on('end', function() {
    console.log('Импорт завершён');
});

В этом примере все проекты из папки /path/to/global-site/import скопируются в папку /path/to/global-site/www как есть, без каких-либо преобразований.

Теперь сделаем так, чтобы во время иморта во всех HTML-файлах переписывались ссылки: к ним добавлялся префикс проекта. Для этого нам нужно зарегистрировать трансформацию для таких файлов с помощью метода addTransform(pattern, factory):

var si = require('site-import');
var through = require('through2');

si.src('/path/to/global-site/import')
.pipe(through.obj(function(project, enc, next) {
    project.addTransform('**/*.html', function() {
        return through.obj(function(file, enc, next2) {
            // переменная `file` -- экземпляр объекта `Vinyl`, как и в Gulp:
            // https://github.com/wearefractal/vinyl
            // Поэтому правильно проверять тип файла: это `Buffer` или `Stream` и соответствующим образом делать обработку. 
            // По умолчанию используется `Buffer`
            var contents = file.contents.toString();

            // добавляем префикс проекта всем ссылкам
            contents = contents.replace(/\shref=(['"])(.+?)\1/g, ' href=$1' + project.prefix + '$2$1');

            file.contents = new Buffer(contents);
            next2(null, file);
        });
    });
    next(null, project);
}))
.pipe(si.dest('/path/to/global-site/www'));

С помощью метода addTransform(pattern, factory) мы зарегистрировали фабрику, которая возвращает поток преобразования (transform stream) файла. Во время переноса каждого файла проекта находятся все трансформации, у которых glob-шаблон pattern матчится на текущий файл и из найденных трансформаций создаётся отдельный pipeline потоков, через который пропускается файл. Таким образом можно очень точечно регистрировать трансформации для конкретных файлов в конкретных проектах, которые могут не только менять содержимое файлов, но и, например, добавлять новые файлы или удалять из потока ненужные.

Данная реализация перезаписи ссылок довольно наивная и не учитывает огромного количества нюансов. Для правильной перезаписи ссылок есть встроенный поток rewriteUrl(), который умеет правильно переписывать ссылки внутри HTML и CSS:

var si = require('site-import');

si.src('/path/to/global-site/import')
.pipe(si.rewriteUrl())
.pipe(si.dest('/path/to/global-site/www'));

Для перезаписи ссылок используются проекты html-transform и css-transform.

About

Импорт статических сайтов в структуру другого сайта

Resources

Stars

Watchers

Forks

Packages

No packages published