Grunt Integration
ByteHide Shield provides a dedicated Grunt plugin that allows you to seamlessly protect your JavaScript code during the build process. This guide explains how to install and configure the Shield Grunt plugin.
Installation
Install the ByteHide Shield Grunt plugin from npm:
npm install --save-dev @bytehide/grunt-shield
Or with yarn:
yarn add --dev @bytehide/grunt-shield
Basic Setup
Add the Shield plugin to your Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
bytehideShield: {
options: {
projectToken: 'your-project-token', // Required: Get this from your ByteHide account
},
dist: {}
}
});
grunt.loadNpmTasks('@bytehide/grunt-shield');
// Register a default task
grunt.registerTask('default', ['bytehideShield']);
};
With this minimal configuration, Shield will apply default protections to your JavaScript files.
Configuration Options
The Grunt plugin accepts the following options:
Option | Type | Default | Description |
---|---|---|---|
projectToken | string | Required | Your ByteHide project token |
distDir | string | 'dist' | Directory containing files to protect |
replace | boolean | false | Whether to replace original files with obfuscated versions |
obfuscatedExtension | string | '.obf' | File extension for obfuscated files (when replace is false ) |
exclude | string[] | [] | Files or patterns to exclude from obfuscation |
config | Object | {} | ByteHide Shield configuration options |
Advanced Configuration
For more advanced use cases, you can provide additional Shield protection options:
module.exports = function(grunt) {
grunt.initConfig({
bytehideShield: {
options: {
projectToken: 'your-project-token',
distDir: 'build',
replace: true,
obfuscatedExtension: '.obf',
exclude: ['vendor/**/*.js', 'polyfills.js'],
config: {
controlFlowFlattening: true,
debugProtection: false,
devtoolsBlocking: false,
stringArray: true,
stringArrayEncoding: ['base64'],
selfDefending: true
}
},
dist: {}
}
});
grunt.loadNpmTasks('@bytehide/grunt-shield');
};
Environment-Specific Configuration
You can apply different protection settings based on the environment:
module.exports = function(grunt) {
// Determine if we're in production mode
const isProd = grunt.option('production') || process.env.NODE_ENV === 'production';
grunt.initConfig({
bytehideShield: {
options: {
projectToken: process.env.BYTEHIDE_PROJECT_TOKEN || 'your-project-token',
replace: isProd, // Only replace files in production
config: {
// More aggressive settings for production
controlFlowFlattening: isProd,
debugProtection: isProd,
devtoolsBlocking: isProd,
// Basic protection for all environments
stringArray: true,
identifierNamesGenerator: 'hexadecimal'
}
},
dist: {}
}
});
grunt.loadNpmTasks('@bytehide/grunt-shield');
// Define different tasks for development and production
grunt.registerTask('build:dev', ['otherTasks', 'bytehideShield']);
grunt.registerTask('build:prod', ['otherTasks', 'set_production', 'bytehideShield']);
// Helper task to set production mode
grunt.registerTask('set_production', function() {
grunt.option('production', true);
});
};
Multi-Target Configuration
You can configure multiple targets for different sets of files:
module.exports = function(grunt) {
grunt.initConfig({
bytehideShield: {
options: {
projectToken: 'your-project-token',
replace: false
},
app: {
options: {
// Target-specific options that override the task options
config: {
controlFlowFlattening: true,
stringArray: true
}
},
files: [{
expand: true,
cwd: 'src/app/',
src: ['**/*.js'],
dest: 'dist/app/'
}]
},
vendor: {
options: {
// Lighter protection for vendor files
config: {
controlFlowFlattening: false,
stringArray: true,
identifierNamesGenerator: 'hexadecimal'
}
},
files: [{
expand: true,
cwd: 'src/vendor/',
src: ['**/*.js'],
dest: 'dist/vendor/'
}]
}
}
});
grunt.loadNpmTasks('@bytehide/grunt-shield');
};
Integration with Other Grunt Tasks
You can integrate Shield with other Grunt tasks in your build workflow:
module.exports = function(grunt) {
grunt.initConfig({
clean: {
dist: ['dist/']
},
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env']
},
dist: {
files: [{
expand: true,
cwd: 'src/',
src: ['**/*.js'],
dest: 'temp/'
}]
}
},
uglify: {
dist: {
files: [{
expand: true,
cwd: 'temp/',
src: ['**/*.js'],
dest: 'dist/'
}]
}
},
bytehideShield: {
options: {
projectToken: 'your-project-token',
replace: true,
config: {
controlFlowFlattening: true,
debugProtection: false,
devtoolsBlocking: false
}
},
dist: {
files: [{
expand: true,
cwd: 'dist/',
src: ['**/*.js'],
dest: 'dist/'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('@bytehide/grunt-shield');
// Define build task
grunt.registerTask('build', [
'clean',
'babel',
'uglify',
'bytehideShield'
]);
};
Complete Example
Here's a complete example of a Grunt configuration with Shield:
module.exports = function(grunt) {
// Determine if we're in production mode
const isProd = grunt.option('production') || process.env.NODE_ENV === 'production';
grunt.initConfig({
// Clean directories
clean: {
dist: ['dist/'],
temp: ['temp/']
},
// Copy files
copy: {
assets: {
files: [{
expand: true,
cwd: 'src/assets/',
src: ['**/*'],
dest: 'dist/assets/'
}]
}
},
// Process JavaScript
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env']
},
dist: {
files: [{
expand: true,
cwd: 'src/js/',
src: ['**/*.js'],
dest: 'temp/'
}]
}
},
// Minify JavaScript
uglify: {
options: {
sourceMap: true
},
dist: {
files: [{
expand: true,
cwd: 'temp/',
src: ['**/*.js'],
dest: 'dist/js/'
}]
}
},
// Protect JavaScript with Shield
bytehideShield: {
options: {
projectToken: process.env.BYTEHIDE_PROJECT_TOKEN || 'your-project-token',
replace: true,
exclude: isProd ? [] : ['**/*.min.js'],
config: {
controlFlowFlattening: isProd,
debugProtection: isProd,
devtoolsBlocking: isProd,
stringArray: true,
stringArrayEncoding: isProd ? ['base64'] : [],
selfDefending: isProd,
identifierNamesGenerator: 'hexadecimal',
reservedNames: [
'^jQuery$', '^\\$',
'^addEventListener$', '^removeEventListener$'
]
}
},
dist: {
files: [{
expand: true,
cwd: 'dist/js/',
src: ['**/*.js'],
dest: 'dist/js/'
}]
}
},
// Watch for changes
watch: {
js: {
files: ['src/js/**/*.js'],
tasks: ['js']
},
assets: {
files: ['src/assets/**/*'],
tasks: ['copy:assets']
}
}
});
// Load tasks
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('@bytehide/grunt-shield');
grunt.loadNpmTasks('grunt-contrib-watch');
// Define custom tasks
grunt.registerTask('js', ['babel', 'uglify', 'bytehideShield']);
grunt.registerTask('build', ['clean', 'copy', 'js']);
grunt.registerTask('default', ['build', 'watch']);
grunt.registerTask('build:prod', ['clean', 'copy', 'set_production', 'js']);
// Helper task to set production mode
grunt.registerTask('set_production', function() {
grunt.option('production', true);
});
};
Troubleshooting
Common Issues
Error: Invalid Token
If you see an error about an invalid token:
- Make sure you're using the correct project token from ByteHide Cloud
- Verify your token has permissions for JavaScript projects
Files Not Being Processed
If your files aren't being protected:
- Check your file paths and globs in the Grunt configuration
- Verify the
distDir
option is set correctly - Make sure the files exist in the specified location
Next Steps
- Get your project token
- Learn about protection options
- Configure exclusions and reserved items