Make service injection private
Domenik Reitzner
Posted on July 14, 2020
This is part five of seven.
Prerequisits
This part is very specific to how this project is set up and depends on what has been done in step four.
Our components/directives/services use the class syntax and bind the injected service to the class to keep the scope clean from services.
class AwesomeComponent {
constructor(MyService) {
Object.assign(this, {MyService});
}
}
The bundle served
After the build process our code will look something like this:
var AwesomeComponent = function() {
AwesomeComponent.$inject = ['MyService'];
function AwesomeComponent(MyService) {
_classCallCheck(this, AwesomeComponent);
Object.assign(this, {
MyService: MyService
});
}
}
Some of you might already see the potential her 😉
The way to privatization
In the last part we have looked at the possibility to minify our private methods (in my project I declare them with _
in the beginning). As our services are exclusively used within the component/directive/service, we could argue that they are injected private Methods.
So the way to optimize our class would be:
class AwesomeComponent {
constructor(MyService) {
Object.assign(this, {
_MyService: MyService,
});
}
}
It would be really boring and prone to mistakes to do all those changes by hand.
So here is my attempt to rework the services with a gulp task (once).
It follows those steps:
- get all js files
- look for the object assign pattern (objectAssignRegex)
- if we have no changes we continue without changes
- get all the services from the capture group and split them into an array
- map through the services and do the private method trick
- join the array with line breaks (
\n
) - wrap them in formatted object assign wrapper
- Replace the old
Object.assign
contents with the generated string - replace all
this.Service
withthis._Service
(careful of $) - overwrite the contents
// make services private
const tPrivateService = () => {
const objectAssignRegex = /Object.assign\(this, \{(.+?)\}/m;
return gulp
.src(packagePath + '/**/*.js', {base: './'})
.pipe(through.obj((file, _, cb) => {
const newFile = file.clone();
let string = newFile.contents.toString();
const match = string.match(objectAssignRegex);
if (match) {
console.log('Working on ', file.basename);
const services = match[1]
.split(', ')
.map((service) => service.trim());
const newServices = services
.map((service) => ` _${service}: ${service},`).join('\n');
const newObjectAssign = match[0]
.replace(match[1], newServices)
.replace('{', '{\n')
.replace('}', '\n }');
string = string.replace(objectAssignRegex, newObjectAssign);
services.forEach((service) => {
string = string.replace(new RegExp(`this.${service.replace(/\$/g, '\\$')}`, 'gm'), `this._${service}`);
});
// overwrite contents of vinyl with new buffer
newFile.contents = Buffer.from(string);
}
cb(null, newFile);
}))
.pipe(gulp.dest('./'));
};
exports.privateService = series(tPrivateService);
In my case, that worked for almost all files. In some cases I had the Object.assign
implemented in a none standard way (with additional var declarations or line breaks).
Before you submit check all your changes.
Enjoy your privatized service injection 🎉
Coming up next
- Privatize unused public methods in components/directives
Posted on July 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.