spa를 연동할 때 assets 번들링에 대해서 알 필요가 있습니다. 과거 운영 프로젝트에서 속도 및 최적화 문제로 js, css를 번들링 하기 위해 gruntjs를 사용했었는데, 요즘의 vite, webpack 프로세스와 비슷하게 동작되어 간단하게 살펴보겠습니다.
//package.json
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-clean": "^2.0.1",
"grunt-contrib-concat": "^2.1.0",
"grunt-contrib-cssmin": "^4.0.0",
"grunt-contrib-uglify": "^5.2.2",
"grunt-filerev": "^2.0.1",
"grunt-filerev-replace": "^0.1.5"
}
//Gruntfile.js
module.exports = function(grunt) {
var originalFiles = {};
grunt.initConfig({
clean: {
user: ['dist/assets/user/*'],
},
concat: {
user_js: {
src: [
'assets/js/jquery.min.js',
'assets/js/jquery.cookie.min.js',
...
],
dest: 'dist/assets/user/user_script.js',
},
user_css: {
src: [
'assets/css/font.css',
'assets/css/default.css',
...
],
dest: 'dist/assets/user/user_style.css',
},
},
cssmin: {
user_css: {
src: [
'dist/assets/user/user_style.css',
],
dest: 'dist/assets/user/user_style.min.css',
},
},
uglify: {
user_js: {
src: [
'dist/assets/user/user_script.js',
],
dest: 'dist/assets/user/user_script.min.js',
},
},
filerev: {
options: {
algorithm: 'md5',
length: 8,
},
user_assets: {
src: ['dist/assets/user/*.{js,css}'],
},
},
filerev_replace: {
options: {
process_relative_path: true,
},
user_views: {
options: {
assets_root: 'dist/assets/user/',
},
src: ['application/views/front/include/includes.php'],
},
},
});
// Load required modules
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-filerev');
grunt.loadNpmTasks('grunt-filerev-replace');
grunt.registerTask('saveOriginalFiles', function(viewType) {
grunt.file.expand({ filter: 'isFile' }, 'dist/assets/' + viewType + '/*').forEach(function(file) {
let nameWithoutHash = file.replace(/(.*)\\.[^.]+\\.(js|css)$/i, '$1.$2');
nameWithoutHash = nameWithoutHash.replace(/\\//g, '\\\\');
originalFiles[nameWithoutHash] = file;
});
});
grunt.registerTask('replaceOriginalFiles', function(viewType) {
let files = grunt.config.get('filerev_replace.' + viewType + '.src');
files.forEach(function(file) {
let content = grunt.file.read(file);
for (let originalFile in originalFiles) {
let revvedFile = grunt.filerev.summary[originalFile];
if (revvedFile) {
content = content.replace(originalFiles[originalFile].replace(/\\\\/g, '/'), grunt.filerev.summary[originalFile].replace(/\\\\/g, '/'));
}
}
grunt.file.write(file, content);
});
});
grunt.registerTask('user', ['saveOriginalFiles:user', 'clean:user', 'concat:user_js', 'concat:user_css', 'uglify:user_js', 'cssmin:user_css', 'filerev:user_assets', 'replaceOriginalFiles:user_views']);
};
순서는 가장 아래에 정의된 registerTask로 진행이 됩니다.
saveOriginalFiles로 이전에 빌드 되어 있는 파일들의 이름을 originalFiles변수에 저장합니다.
clean:user : 이전에 만든 번들링 파일을 모두 지웁니다.
concat:user_js, concat:user_css : 내가 작성한 js와 css를 모두 합쳐서 하나의 결과물을 만듭니다.
uglify:user_js : 자바스크립트 같은 경우에는 해독을 어렵게 만듭니다.
cssmin:user_css : css를 작게 만듭니다.
filerev_replace : <script>, <style> 등 번들링된 스크립트와 css를 import하는 곳을 지정합니다 여기서는 include.php 입니다.
replaceOriginalFiles:user_views : filerev_replace에서 지정한 include.php 파일의 내용을 돌면서 이전에 만든 번들링 파일을 찾아 모두 새로운 번들링 파일 네임으로 변경 합니다.
gruntjs 동작은 vite 빌드 방식과 굉장히 유사합니다. 다만 vite는 애플리케이션의 모든 컴포넌트 및 의존성들이 포함되어 하나의 script와 css를 가집니다.