Require.js+backbone using R.js in-place with production environment one-click Compression implementation time:2017-07-03 17:18:11 Read:210 Comments:0 Favorites:0 [Point I collection +]
Tags: fonts mil bin Mat file configuration folder ODI frame return
Requie.js and Backbone.js here will not say, can go to see the official documents, are very specific!
However, the use of require.js default with the compression mode is not very convenient, so this article is mainly about the use of r.js compression, to achieve local non-compression, production environment compression
R.js is executed on node, using UGLIFYJS by default. Uglifyjs really very useful, then why is the default way is not very convenient?
R.js compressing a file individually is also very useful, but in the actual project. Can not be a one-pressure bar! So R.js provides a way to compress multiple files
, a configuration file called Bulid.js is used to configure the module so that multiple modules can be compressed.
But. There are several issues:
1. To maintain a profile, the more modules, the more difficult to maintain. Of course, can also write a self-generated configuration file script, personal feeling is not good, because of the second problem.
2. After compression, a full copy of the entire directory compression will be generated, so you will have to submit two JS directories to your code base. And the code redundancy exists in the compressed directory. Since all of the code will be loaded into a portal file that is compressed based on the layer dependencies, loading is just a matter of loading the portal file, but the other files are also compressed. is copied to the new directory.
3. Compression every time all compression, the efficiency is very low!
Partial compression can also be achieved. I just didn't find the right way.
4. The local use of uncompressed, compressed after submission, there is no guarantee that 100% compression is correct (in case the dependency in the configuration error), so it needs to be submitted to the test environment talent discovery.
The problem is over, there is a welcome reply that can be solved. Here's how I do it.
Window development Environment &&node Environment &&apache need to open rewrite and ETag.
The first is about the principle:
A total of two steps, 1 is the merger; 2 is compression;
1. Use the Apche. htaccess file to redirect the requested JS file (/js/dist/home.js) to a PHP script (local environment) and pass the/js/src/main/home.js as a parameter. In this script, it is necessary to infer whether there is a need to merge (this is simply merging, not compressing). Use R.js to merge into a home.dev.js under the/js/dist folder. The token of the ETag is then generated based on the time it depends on the file change. Sets the etag and outputs the content.
Assume that there is no need to merge (inferred from the ETag). Then directly return 304, to read the previous cache: This is a merged but uncompressed JS file that is loaded locally for easy debugging.
2. This home.dev.js does not need to be submitted by your code base, just keep it locally. There is also a PHP script that needs to be added. Called by a batch.
The role of the script is to home.dev.js again the same folder compression out of a home.js, here also need to root home.js whether exist and home.js and home.dev.js file change time to do compare, to infer whether compression. Compressed home.js, even if submitted to the code base (from home.dev.js to Home.js, is equivalent to a single file compression. There is no dependency, so the probability of error is very small and very small. Very good to overcome the above-mentioned questions).
Below is the detailed implementation method:
1. The folder structure is this:
The simple explanation
On the left is the JS folder structure diagram. LIB is the core framework, such as jquery, plugin is put into the plug-in, common is put into their own written public module.
SRC is the source of the application. Main is the entry file.
The dist is placed merged and compressed, and the file name is the same as in main. The other is the backbone folder structure, there may be some not comprehensive, here first not considered.
The folder to the right is the compressed script. R.js is the require.js provided by the compression JS script, Compile.bat call the Compressed script batch file, combine_js.php Merge code php script, conplile.php is the compression code of the script, notmodified.php is to infer whether a merger is required. The principle is to use the dependent file change time to generate the ETag token,combine_css.php is a combination of CSS script, after the JS compression.
2. Understand the structure and basic principles of the folder, and the rest is the paste code.
Introduction of HTML:
<script data-main= "/js/dist/home" src= "/js/lib/require-2.1.14.min.js" ></script>
The entrance to the program is Js/dist/home, which is merged and compressed by Js/scr/mian/home.js, which is used in the production environment.
In the local environment, we have to rely on. htaccess this file.
. htaccess
# REDIRECT Js/dist/home.js to combine_js.php This script, and replace Dist with main,#, js/src/main/home.js this true portal file path as a reference pass Rewritecond%{ Request_filename} ^ (. *) dist (. *\.js) $rewriteCond%1src/main%2-frewriterule ^ (. *) dist (. *\.js) $ build/combine_js.php?
f=$1src/main$2 [b,l] #css的合并. And the same as above. Just the corresponding script is processed differently Rewritecond%{request_filename} ^ (. *) dist (. *\.css) $ rewritecond%1config%2-f rewriterule ^ (. *) dist (. *\. CSS) $ build/combine_css.php?f=$1config$2 [L] #假设xxx. (js| | CSS) has a corresponding xxx.dev. (js| | CSS) is redirected to the. dev.js or. Dev.css #这个是给已经合并和已经压缩好的js或css to use the #比方lib/jquery.js, you can download the corresponding debug version locally, change the file name is called Jquery.dev.js, In this way the local can also debug jquery rewritecond%{request_filename} ^ (. *) \. (JS|CSS) $ rewritecond%1.dev.%2-f rewriterule ^ (. *) \. (JS|CSS) $ $1.dev.$2 [L]
Here's the key combine_js.php.
<?
php include ' notmodified.php '; Define (' BASE ', DirName (__file__)); $file _main = BASE. ' /.. /'. $_get[' F ']; $file _config = BASE. ' /.. /js/config.js '; $comment _reg_exp = '/(\/\* ([\s\s]*?
)\*\/| ([^:]|^) \/\/(. *) $)/M '; $js _require_reg_exp = '/[^. \s*require\s*\ (\s*[\ "\"] ([^\ ' \ "\s]+) [\" \ ']\s*\]/'; $exclude _reg_exp = '/\s*exclude\s*:\s* (\[.*?\])/s '; $alias _reg_exp = '/\s*paths\s*:\s* (\{.*?
\})/s '; $data _dep_file = Array ($file _main, $file _config); An array of //dependent files, containing both itself and the config file $data _ex_dep_file = array (); //non-compressed dependent file array $data _alias_file = "; //aliased file string if (File_exi STS ($file _config)) { $text _config = file_get_contents ($file _config); $text _config = Preg_ Replace ($comment _reg_exp, ", $text _config); //Remove gaze Preg_match_all ($exclude _reg_exp, $text _config, $matches); if (Isset ($matches [1][0])) { //Remove a dependent file configuration that does not require compression $data _ex_dep_file = Json_ Decode (Str_replace ("\ n", "", Str_replace ("", "", Str_replace ("'", ' "', $matches [1][0])), true); Preg_match_all ($alias _reg_exp, $text _config, $matches); if (Isset ($matches [1][0])) { //Remove the true file configuration with aliases $data _alias_File = Str_replace ("\ n", "", Str_replace ("", "", Str_replace ("'", ' "', $matches [1][0]))); } } function Get_true_path ($alias) { //Remove the true file name of the alias Global $data _alias_fil E $alias _escape = Str_replace ('. ', ' \. ', Str_replace ('/', ' \ \ ', $alias)); $REGEXP = '/'. $alias _escape. ': ' (. *?) " /‘; Preg_match_all ($REGEXP, $data _alias_file, $matches); if (Isset ($matches [1][0]) { return $matches [1][0]; } return $alias; } function Get_dep_files ($file _name) { global $js _require_reg_exp, $data _dep_file, $data _ex_dep_file, $ Comment_reg_exp; if (file_exists ($file _name)) { $text _main = file_get_contents ($file _name); $text _main = preg_replace ($comment _reg_exp, ", $text _main); Preg_match_all ($js _require_reg_exp, $text _main, $matches); if (Isset ($matches [1]) && Is_array ($matches [1]) && count ($matches [1]) > 0) { //take out dependent files & nbsp foreach ($matches [1] as $v) { $V = Trim ($v); $v _true = Get_true_path ($v); $v _path = BASE. ' /.. /js/'. $v _true. (STRRCHR ($v, '. ') = = '. js '? ': '. js '); Full path of the file //depends on if (!in_array ($v, $data _ex_dep_file) && ;!in_array ($v _path, $data _dep_file)) { $data _dep_fil e[] = $v _path; Get_dep_files ($v _path); Recursive take-out dependent files &N. Bsp } }} get_dep_files ($file _main); $ext = STRRCHR ($file _main, '. '); $file _name = basename ($file _main, $ext); $file _source = ' src/main/'. $file _name; $file _output = BASE. ' /.. /js/dist/'. $file _name. Dev.js '; if (file_exists ($file _output) && notmodified ($data _dep_file)) { //generates an etag based on the dependent file churn time to infer if compression is required Exit; } $output = Array (); $error = Array (); EXEC (' node R.js-o mainconfigfile= '. BASE. ' /.. /js/config.js baseurl= '. BASE. ' /.. /js/name= '. $file _source. ' out= '. $file _output. ' Optimize=none ', $output); &NBSP;//uses node compression to generate the dev file and save the output. foreach ($output as $v) { if (Preg_match ('/error/', $v)) { $error []=json_encode ($v) ; Save error message } if (empty ($error)) { header (' Content-type:application/javascript '); Echo file_get_contents ($file _output); exit; } foreach ($error as $e) { echo "console.error ($e);";//Output error message} exit;
Here are the notmodified.php
function notmodified ($files = Array ()) {$s = ' ', if (is_string ($files)) {$files = array ($files); } if ($files) {foreach ($files as $f) {$s. = Filemtime ($f);//splicing depends on the file change time, the token used to generate the ETag }} $etag = sprintf ('%08x ', CRC32 ($s)); Header ("ETag: \" $etag \ "");//Output ETag if (isset ($_server[' Http_if_none_match ')) && strpos ($_server[' http_if_ None_match '], $etag)) {header (' http/1.1 304 not Modified ');//If no change is made, 304 is returned. Go to read cache return true;} return false;}
Below is a look at the entry file Main/spc.js
Require (["config.js"], Function (config) {<span style= "font-family:arial, Helvetica, Sans-serif;" After the >//loads the public configuration file, it starts to define the module.
</span> require ([' src/main/home ']); }); Define (function (require) {"Use strict"; var home = require ("Src/controllers/home"); New Home ({name: ' HomeController '}). init (); });
Here's a look at the public profile Config.js This has been done most of the work, and the last production of the compression work
/* * default Config. */requirejs.config ({ baseurl:typeof (javascriptserver) = = = ' undefined '? ': Javascriptserver + ' js/', paths: { jquery: ' Lib/jquery-1.11.1.min ', &nbs P Underscore: ' Lib/underscore-1.6.min ', backbone: ' Lib/backbone-1.1.2.min ', cookies: ' Plugin/jquery.cookie ' }, usestrict:true, EX Clude: [' jquery ', ' underscore ', ' backbone ', ' cookie '],//Do not need to merge files, use R.js to merge or compress. Read this configuration file: node R.js-o mainconfigfile= '. BASE. ' /.. /js/config.js ...... Shim: { /* Now backbone and underscore are supported amd! If the version number is not supported, the following configuration is required. backbone: { deps: [' jquery ', ' underscore '], &NB Sp exports: ' Backbone ' }, underscore: {&nbs P &NBsp Exports: ' _ ' } */ }});
See batch Compile.bat First, very easy
@echo offphp compile.php ". /js/dist "PHP compile.php". /css/dist "Pause
See compile.php again, very easy
define (' base ', DirName (__file__)), if ($ARGC = = 1) {compile (base);} Else{compile (BASE. ') /'. $ARGV [1]);} function Compile ($dir) {$h = Opendir ($dir), while (($f = Readdir ($h))!== false) {if ($f = = '. ' | | $f = = ' ... ') {continue; } $f = $dir. '/'. $f; if (Is_dir ($f)) {compile ($f);} else if (substr ($f, -7) = = '. Dev.js ') {//js $ext = STRRCHR ($f, '. '); $out = substr ($f, 0,-7). JS '; if (!file_exists ($out) | | filemtime ($F) > Filemtime ($out)) {System (' node R.js-o mainconfigfile= '. BAS E. '/. /js/config.js baseurl= '. BASE. ' /.. /js/name=app/product/'. basename ($f, $ext). ' out= '. $out); System (' jsl-process. /js/app/product/'. basename ($f, $ext). JS '); JSLint Check Syntax}}else if (substr ($f, -8) = = '. Dev.css ') {//css$out = substr ($f, 0,-8). CSS '; if (!file_exists ($out) | | filemtime ($F) > Filemtime ($out)) {System (' node R.js-o cssin= '. $f. ' out= '. $out. ' Optimizecss=standard '); }}}closedir ($h);}
Finally, I want to say. In fact, there are two of these routines that tolerate small bugs. Usually need to pay attention to.
1. Assume (forward) that the local time has been changed. Compression may cause compression to fail.
Workaround: Turn the time right. Delete produt/xxx.js, update it again from the version number library, and then compress.
In fact, be careful not to change the local time when compressing.
2. Assuming ctrl+f5 or emptying the cache, even if the file is not changed, it will be merged again. Because the etag was cleared.
The solution: The problem is in fact no tube, assuming that it is not modified by the compression again, do not commit can be. It's not too much of a relationship to submit!
Now just endure, assuming there is a good way to welcome the guidance.
Wait, there's time. The entire set of source code will be compiled on GitHub.
Require.js+backbone implementation of one-click compression using R.js in local and production environments
Tags: fonts mil bin Mat file configuration folder ODI frame return
Original address: http://www.cnblogs.com/lytwajue/p/7111887.html
Require.js+backbone using R.js for local and production environment one-click Compression implementation