Как минимизировать js файлы в порядке через grunt-contrib-uglify?
У меня есть каталог, как показано ниже:
/folder/b.js
/folder/jQuery.js
/folder/a.js
/folder/sub/c.js
Я хочу минимизировать все эти js файлы в одном файле js в порядке:
jQuery.js → a.js → b.js → c.js
Q:
1.Как я могу сделать это через grunt-contrib-uglify? (На самом деле, есть много файлов, нецелесообразно указывать все исходные файлы файлы в отдельности)
2.btw, как я могу получить unminified файлы при отладке и получить минимальный один файл при выпуске и не нужно менять тег script в html (и как писать тег script)?
Ответы
Ответ 1
Хорошие вопросы!
1) Uglify будет изменять порядок функций в целевом файле, чтобы определения функций находились сверху и выполнялись в нижней части, но, похоже, он сохранит порядок выполнения функций.
Это означает, что функция jQuery выполняется для определения ее глобальных функций, прежде всего, если вы убедитесь, что jQuery упоминается сначала в конфигурации Uglify в файле Grunt.
Я использую эту конфигурацию:
uglify: {
options: {
sourceMap: true
},
build: {
files: {
'public/all.min.js': ['public/js/vendor/jquery-1.10.2.min.js', 'public/js/*.js'],
}
}
}
2) Я не думаю, что есть один определенный способ сделать это. Это зависит от того, какие веб-рамки, рамки шаблонов и какие у вас есть требования. Я использую express + jade, и в моем основном дизайне нефрита я:
if process.env.NODE_ENV === 'production'
script(src='/all.min.js')
else
script(src='/js/vendor/jquery-1.10.2.min.js')
script(src='/js/someScript.js')
script(src='/js/otherScript.js')
В моем пакете .json у меня есть:
"scripts": {
"postinstall": "grunt"
},
Это означает, что когда я запускаю npm install
при развертывании (на Heroku), grunt запускается для minify/concat файлов, а когда приложение запускается с NODE_ENV=production
, используется javascript с миниатюрной клиентской стороной. Локально я получаю исходные javascripts на стороне клиента для легкой отладки.
Двумя минутами являются:
- Мне нужно синхронизировать два списка файлов script (в файле Gruntfile и в layout.js). Я решаю это, используя
*.js
в файле Grunt, но это может не соответствовать всем. Вы можете поместить список javascripts в Gruntfile и создать из него jade-шаблон, но для большинства проектов это кажется излишним.
- Если вы не доверяете своей конфигурации Grunt, вам в основном нужно протестировать запуск приложения с помощью
NODE_ENV=production
локально, чтобы убедиться, что минимизация работает так, как вы планировали.
Ответ 2
Это можно сделать, используя следующие задачи Grunt:
ИЗМЕНИТЬ
Я обычно запускаю все свои файлы с помощью задачи конкатенации Grunt, используя grunt-contrib-concat. Тогда у меня есть еще одна задача - обрезать конкатенированный файл с помощью grunt-contrib-uglify.
Ответ 3
Вам, вероятно, не понравится это, но лучший способ - определить исходные файлы js как модули AMD и использовать Requirejs для управления порядком, в котором они загружаются. Задача grunt-contrib-requirejs рекурсирует ваше дерево зависимостей и объединит файлы js в необходимом порядке в один большой файл js. Затем вы будете использовать uglify (на самом деле r.js имеет встроенный встроенный), чтобы минимизировать большой файл.
https://github.com/danheberden/yeoman-generator-requirejs имеет хороший пример файлов gruntfile и js файлов шаблонов для работы.
ИЗМЕНИТЬ
Недавно я начал использовать модули CommonJS вместо AMD, так как он намного ближе к спецификации модуля ES6. Вы можете добиться тех же результатов (1 большой файл с согласованным + конкатенированным js), запустив модули commonjs через Browserify. Существуют плагины для grunt и gulp для управления этой задачей.
ИЗМЕНИТЬ
Я хотел бы добавить, что если ваш сайт написан с использованием ES6, Rollup является лучшим новым конкатенирующим пакетом. Помимо связывания ваших файлов, он также будет выполнять дрожание дерева, удаляя части библиотек, которые вы используете, если они включены в оператор import
. Это уменьшает вашу кодовую базу до того, что вам нужно без раздувания кода, который вы никогда не будете использовать.
Ответ 4
Я не думаю, что вы можете сделать это с помощью задачи uglify, но у вас есть множество вариантов, которые могут привести к желаемому результату.
Возможный рабочий процесс будет сначала конкатенировать (grunt-contrib-concat) файлы по порядку в один файл и поместить этот конкатенированный файл через uglify. Вы можете либо определить порядок concat в своем файле Grunt, либо использовать эти плагины:
Сначала будет https://github.com/yeoman/grunt-usemin, где вы можете указать порядок в своем HTML файле, поместите некоторые комментарии вокруг своего блока script. Ребята из Google сделали это, и это довольно мило для использования.
Во-вторых, https://github.com/trek/grunt-neuter, где вы можете определить некоторые зависимости с требованием, но без основной суммы require.js. Это требует изменений в вашем JS-коде, поэтому может не понравиться. Я бы выбрал один вариант.
Ответ 5
Я столкнулся с той же проблемой. Быстрое исправление - это просто изменить имена файлов - я использовал 1.jquery.min.js
, 2.bootstrap.min.js
и т.д.
Ответ 6
Это может быть только отдаленно связано с вашим вопросом, но я хотел что-то подобное. Только мой заказ был важен следующим образом:
Я загружал все файлы поставщиков (angular, jquery и их соответствующие связанные плагины) с помощью подстановочного знака (['vendor/**/*.js']
). Но некоторые плагины имели имена, которые заставляли их загружать до angular и jquery. Решение состоит в том, чтобы вручную загрузить их в первую очередь.
['vendor/angular.js', 'vendor/jquery.js', 'vendor/**/*.js]
К счастью, angular и дескриптор jquery загружаются дважды достаточно хорошо. Изменить: Хотя это не самая лучшая практика для загрузки таких больших библиотек дважды, что приводит к ненужному раздуванию вашего мини файла. (спасибо @Kano за указание этого!)
Еще одна проблема заключалась в том, что заказ-js был важным для того, чтобы он загружал основной файл приложения, после того как все его зависимости были загружены. Решение этого было исключить, а затем включить:
['app/**/*.js', '!app/app.js', 'app/app.js']
Это предотвращает загрузку app.js
вместе со всеми другими файлами и только затем включает его в конце.
Ответ 7
Похоже, вторая часть вашего вопроса все еще остается без ответа. Но позвольте мне попробовать один за другим.
Во-первых, вы можете присоединить и убрать большое количество js файлов в один, как объяснялось ранее ответом concat. Также должно быть возможно использовать https://github.com/gruntjs/grunt-contrib-uglify, поскольку он, похоже, имеет подстановочные знаки. Возможно, вам придется экспериментировать с опцией "expand = true" и подстановочными знаками. Это позаботится о вашем первом вопросе.
Для второй части, скажем, вы присоединились и угадали в big-ugly.js
Теперь в вашем html вы можете добавить следующие директивы:
<!-- build:js:dist big-ugly.js -->
<script src="js1.js"></script>
<script src="js2.js"></script>
<!-- etc etc -->
<script src="js100.js"></script>
<!-- /build -->
И затем передайте его через прерывный hunt-html-препроцессор в https://www.npmjs.com/package/grunt-processhtml как часть ваших заданий на grunt.
Этот препроцессор заменит весь блок на
<script src="big-ugly.js"></script>
Это означает, что html файл должен быть семантически эквивалентным - до и после заданий grunt; то есть, если страница работает правильно в нативной форме (для отладки) - тогда преобразованная страница должна работать правильно после grunt - без необходимости вручную изменять любые теги.
Ответ 8
Это был ответ @1469, но он не дал понять, почему это работает. Используйте concat, чтобы поместить все js файлы в один, этот модуль делает это в порядке имен файлов, поэтому я помещаю префикс в имена файлов по заказам. Я считаю, что у него даже есть другие варианты для заказа.
concat: {
js: {
options: {
block: true,
line: true,
stripBanners: true
},
files: {
'library/dist/js/scripts.js' : 'library/js/*.js',
}
}
},
Затем используйте uglify для создания миниатюрной уродливой версии:
uglify: {
dist: {
files: {
'library/dist/js/scripts.min.js': [
'library/js/scripts.js'
]
},
options: {
}
}
},
Ответ 9
Если ваша проблема заключалась в том, что у вас были поставщики, которые нужно было загрузить по порядку (скажем, jquery перед любыми плагинами jquery). Я решил это, поставив jquery в свою собственную папку под названием "! Jquery", эффективно помещая ее поверх стека.
Тогда я просто использовал concat, как обычно:
concat: {
options: {
separator: ';',
},
build: {
files: [
{
src: ['js/vendor/**/*.js', 'js/main.min.js'],
dest: 'js/global.min.js'
}
]
}
},