During front-end development, we often package and merge programs during deployment and launch. Next we will discuss how to use Node. js development front-end package program for a very in-depth explanation, hope to help students in need.
Currently, we are working on front-end development with more people working together. Each person is responsible for different modules to facilitate development and debugging. In this way, the modules developed by all users need to be merged during the final deployment and launch to generate one or more files. Manual merge is time-consuming, labor-consuming, and error-prone. Therefore, we generally use some tools to implement automatic merge.
The principle of the package is very simple. Go to the File> Search for dependency> replace dependency> Generate a file. The two steps in the middle are recursively executed.
Let's take a look at how to use node. js to complete a simple file merging function:
// Package file content
Var contentList = [];
// Weight list
Var loadedFileList = {};
// Package the main program
Function combine (filePath ){
// Obtain the content of the entry file.
Var fileContent = fs. readFileSync (filePath );
// Traverse the File Content
FileContent. forEach (function (value ){
// Here, findImport is the method that you need to implement. use regular expressions to match dependencies.
Var matchFile = findImport (value );
If (matchFile ){
// If the dependency is matched
If (! LoadedFileList [matchFile]) {
// If the dependency is not in the weight list, recursively call combine.
Combine (matchFile );
ContentList. push ('\ n ');
}
} Else {
ContentList. push (value );
}
});
}
Finally, you only need to generate a file based on the content in the contentList. How is it easy? Next we will introduce another method to use stream to complete our packaging program.
In node. js, Stream is an abstract interface implemented by different objects. A stream can be readable, writable, or both readable and writable. All streams are EventEmitter instances. We can use the inheritance interface to construct the stream we need. Two streams are required in our package. One is responsible for outputting the file content in line, and the other is responsible for processing dependencies. All the file contents flow cyclically in the two streams. When all the dependencies are processed, the flow ends and the corresponding file is generated. This achieves our goal.
Let's take a look at how the stream is responsible for outputting the file content by row:
Var Stream = require ('stream'). stream,
Util = require ('til '),
Path = require ('path '),
Fs = require ('fs ');
// Constructor
Function LineStream (){
This. writable = true;
This. readable = true;
This. buffer = '';
}
Module. exports = LineStream;
// Inherit the stream interface
Util. inherits (LineStream, Stream );
// Rewrite the write method. This method is called for all pipe data.
LineStream. prototype. write = function (data, encoding ){
Var that = this;
// Convert the buffer to the string type
If (Buffer. isBuffer (data )){
Data = data. toString (encoding | 'utf8 ');
}
Var parts = data. split (/\ n/g );
// If the last buffer exists, add it to the beginning.
If (this. buffer. length> 0 ){
Parts [0] = this. buffer + parts [0];
}
// Traverse and send data
For (var I = 0; I <parts. length-1; I ++ ){
This. emit ('data', parts [I]);
}
// Save the last row of data to the buffer so that the transmitted data remains continuous and complete.
This. buffer = parts [parts. length-1];
};
// End method, called at the end of the stream
LineStream. prototype. end = function (){
// If there is a buffer, send it out
If (this. buffer. length> 0 ){
This. emit ('data', this. buffer );
This. buffer = '';
}
This. emit ('end ');
};
In this way, our lineStream is complete. We can see that we have done one thing in the write method, breaking down the transmitted data and sending it by row, then let's take a look at the stream DepsStream that processes dependencies.
Var stream = require ('stream'). stream;
Var util = require ('til ');
Var fs = require ('fs ');
Var path = require ('path ');
Module. exports = DepsStream;
Util. inherits (DepsStream, stream );
Function DepsStream (){
This. writable = true;
This. readable = true;
This. buffer = '';
This. depsList = [];
};
// The write method here only sends data and does not process the data.
DepsStream. prototype. write = function (data ){
This. emit ('data', data );
};
// Here we repeat the pipe method to enable it to process dependencies and generate final files.
DepsStream. prototype. pipe = function (dest, opt ){
Var that = this;
Function ondata (chunk ){
Var matches = findImport (chunk );
If (matches ){
If (this. depsList. indexOf (matches)> = 0 ){
// Here we will pipe the processed data back to lineStream
Dest. write ('\ n ');
} Else {
This. depsList. push (matches );
Var code = getFileContent (matches );
// Here we will pipe the processed data back to lineStream
Dest. write ('\ n' + code );
}
} Else {
This. buffer + = chunk + '\ n ';
}
}
Function onend (){
// Generate the final file
Var code = this. buffer;
Fs. writeFileSync (filePublishUrl, code );
Console. log (filePublishUrl + 'combine done .');
}
// Listen to the end event
That. on ('end', onend );
// Listen to data Events
That. on ('data', ondata );
};
// End Method
DepsStream. prototype. end = function (){
This. emit ('end ');
};
We can see that in the above program, we listened to the end event and data event in the pipe method. The ondata method is mainly used to process data, if a dependency is found, the file corresponding to the dependency is obtained and sent back to LineStream for processing. The onend method is used to generate the final file. Let's take a look at the final call method:
Var fileStream = fs. createReadStream (filepath );
Var lineStream = new LineStream ();
Var depsStream = new DepsStream ();
FileStream. pipe (lineStream );
LineStream. pipe (depsStream );
DepsStream. pipe (lineStream );