Min.php 5.8 KB

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