Min.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // |
  4. // +----------------------------------------------------------------------
  5. // |
  6. // +----------------------------------------------------------------------
  7. // |
  8. // +----------------------------------------------------------------------
  9. // |
  10. // +----------------------------------------------------------------------
  11. // | Original reference: https://gitee.com/karson/fastadmin
  12. // +----------------------------------------------------------------------
  13. // +----------------------------------------------------------------------
  14. // | r.js压缩主程序
  15. // +----------------------------------------------------------------------
  16. namespace app\admin\command;
  17. use think\console\Command;
  18. use think\console\Input;
  19. use think\console\input\Option;
  20. use think\console\Output;
  21. use think\Exception;
  22. class Min extends Command
  23. {
  24. /**
  25. * 路径和文件名配置
  26. */
  27. protected $options = [
  28. 'cssBaseUrl' => 'public/assets/css/',
  29. 'cssBaseName' => '{module}',
  30. 'jsBaseUrl' => 'public/assets/js/',
  31. 'jsBaseName' => 'require-{module}',
  32. ];
  33. protected function configure()
  34. {
  35. $this
  36. ->setName('min')
  37. ->addOption('module', 'm', Option::VALUE_REQUIRED, 'module name(frontend or backend),use \'all\' when build all modules', null)
  38. ->addOption('resource', 'r', Option::VALUE_REQUIRED, 'resource name(js or css),use \'all\' when build all resources', null)
  39. ->addOption('optimize', 'o', Option::VALUE_OPTIONAL, 'optimize type(uglify|closure|none)', 'none')
  40. ->setDescription('Compress js and css file');
  41. }
  42. protected function execute(Input $input, Output $output)
  43. {
  44. $module = $input->getOption('module') ?: '';
  45. $resource = $input->getOption('resource') ?: '';
  46. $optimize = $input->getOption('optimize') ?: 'none';
  47. if (!$module || !in_array($module, ['frontend', 'backend', 'all'])) {
  48. throw new Exception('Please input correct module name');
  49. }
  50. if (!$resource || !in_array($resource, ['js', 'css', 'all'])) {
  51. throw new Exception('Please input correct resource name');
  52. }
  53. $moduleArr = $module == 'all' ? ['frontend', 'backend'] : [$module];
  54. $resourceArr = $resource == 'all' ? ['js', 'css'] : [$resource];
  55. $minPath = __DIR__ . DS . 'Min' . DS;
  56. $publicPath = app()->getRootPath() . 'public' . DS;
  57. $tempFile = $minPath . 'temp.js';
  58. $nodeExec = '';
  59. if (!$nodeExec) {
  60. if (strpos(PHP_OS, 'WIN') !== false) {
  61. // Winsows下请手动配置配置该值,一般将该值配置为 '"C:\Program Files\nodejs\node.exe"',除非你的Node安装路径有变更
  62. $nodeExec = 'C:\Program Files\nodejs\node.exe';
  63. if (file_exists($nodeExec)) {
  64. $nodeExec = '"' . $nodeExec . '"';
  65. } else {
  66. // 如果 '"C:\Program Files\nodejs\node.exe"' 不存在,可能是node安装路径有变更
  67. // 但安装node会自动配置环境变量,直接执行 '"node.exe"' 提高第一次使用压缩打包的成功率
  68. $nodeExec = '"node.exe"';
  69. }
  70. } else {
  71. try {
  72. $nodeExec = exec("which node");
  73. if (!$nodeExec) {
  74. throw new Exception("node environment not found!please install node first!");
  75. }
  76. } catch (Exception $e) {
  77. throw new Exception($e->getMessage());
  78. }
  79. }
  80. }
  81. foreach ($moduleArr as $mod) {
  82. foreach ($resourceArr as $res) {
  83. $data = [
  84. 'publicPath' => $publicPath,
  85. 'jsBaseName' => str_replace('{module}', $mod, $this->options['jsBaseName']),
  86. 'jsBaseUrl' => $this->options['jsBaseUrl'],
  87. 'cssBaseName' => str_replace('{module}', $mod, $this->options['cssBaseName']),
  88. 'cssBaseUrl' => $this->options['cssBaseUrl'],
  89. 'jsBasePath' => str_replace(DS, '/', app()->getRootPath() . $this->options['jsBaseUrl']),
  90. 'cssBasePath' => str_replace(DS, '/', app()->getRootPath() . $this->options['cssBaseUrl']),
  91. 'optimize' => $optimize,
  92. 'ds' => DS,
  93. ];
  94. //源文件
  95. $from = $data["{$res}BasePath"] . $data["{$res}BaseName"] . '.' . $res;
  96. if (!is_file($from)) {
  97. $output->error("{$res} source file not found!file:{$from}");
  98. continue;
  99. }
  100. if ($res == "js") {
  101. $content = file_get_contents($from);
  102. preg_match("/require\.config\(\{[\r\n]?[\n]?+(.*?)[\r\n]?[\n]?}\);/is", $content, $matches);
  103. if (!isset($matches[1])) {
  104. $output->error("js config not found!");
  105. continue;
  106. }
  107. $config = preg_replace("/(urlArgs|baseUrl):(.*)\n/", '', $matches[1]);
  108. $config = preg_replace("/('tableexport'):(.*)\,\n/", "'tableexport': 'empty:',\n", $config);
  109. $data['config'] = $config;
  110. }
  111. // 生成压缩文件
  112. $this->writeToFile($res, $data, $tempFile);
  113. $output->info("Compress " . $data["{$res}BaseName"] . ".{$res}");
  114. // 执行压缩
  115. $command = "{$nodeExec} \"{$minPath}r.js\" -o \"{$tempFile}\" >> \"{$minPath}node.log\"";
  116. if ($output->isDebug()) {
  117. $output->warning($command);
  118. }
  119. echo exec($command);
  120. }
  121. }
  122. if (!$output->isDebug()) {
  123. //@unlink($tempFile);
  124. }
  125. $output->info("Build Successed!");
  126. }
  127. /**
  128. * 写入到文件
  129. * @param string $name
  130. * @param array $data
  131. * @param string $pathname
  132. * @return mixed
  133. */
  134. protected function writeToFile($name, $data, $pathname)
  135. {
  136. $search = $replace = [];
  137. foreach ($data as $k => $v) {
  138. $search[] = "{%{$k}%}";
  139. $replace[] = $v;
  140. }
  141. $stub = file_get_contents($this->getStub($name));
  142. $content = str_replace($search, $replace, $stub);
  143. if (!is_dir(dirname($pathname))) {
  144. mkdir(strtolower(dirname($pathname)), 0755, true);
  145. }
  146. return file_put_contents($pathname, $content);
  147. }
  148. /**
  149. * 获取基础模板
  150. * @param string $name
  151. * @return string
  152. */
  153. protected function getStub($name)
  154. {
  155. return __DIR__ . DS . 'Min' . DS . 'stubs' . DS . $name . '.stub';
  156. }
  157. }