springboot+gulp+bower+资源压缩+CDN全栈

随着时代的发展,越来越多的技术蜂拥出来,而web技术也从之前单一的单一打包,放到web容器中运行。逐渐发展成了,js压缩,sass编译成css然后在压缩,sourceMap的引入,CDN的引入等等。这篇文章就是一个大一统的解决方案。不卖关子了,下面介绍一下本篇文章的目的。
本篇文章用一个spring boot实现如下功能:

  1. 使用spring boot + 内嵌tomcal + jsp 实现web容器
  2. 前端使用 angular js + sass + bower + npm + gulp 做前端开发
  3. 前端 sass 编译 + css 压缩 + sourcemap + 版本 + CDN
  4. 前端 JS 格式化校验 + JS 压缩 + 版本 + CDN
    项目路径如下 spring boot CDN 项目。 项目截图如下
    项目效果图如下 整个项目所以来的所有js被压缩成了两个一个是 lib-all.js(自己写js)(所有外部引入的js如angularjs, jquery等) 和 app-all.js分别用gulp给每一个js加上了版本。项目所有css被压缩成了两个,一个是 app-all.css 和 external-all.css也被打上版本,加上CDN路径。


开始正戏: 介绍如何实现

搭建spring boot 工程

项目路径如下 spring boot CDN 项目

pom 文件

项目路径已经列出来了,具体pom可以见github,这里只是把重点的pom内容列出来

首先定义pom的打包方式为 war

项目路径如下 spring boot CDN 项目

    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>spring-gulp-rev-cd</name>
    <description>Demo project for Spring Boot</description>

然后引入 web项目基本依赖

项目路径如下 spring boot CDN 项目

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- JSTL for JSP -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
</dependencies>

引入编译war包的编译的核心插件

项目路径如下 spring boot CDN 项目
这里mainclass如果不指定,那么 mvn package的 war包无法直接运行。 不加repackage也可以,但是这时候你在打包的时候要用 mvn clean package spring-boot:repackage -Pprod

 <plugin>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-maven-plugin</artifactId>
     <configuration>
     <fork>true</fork>
     <mainClass>com.springgulprevcdn.SpringGulpRevCdnApplication</mainClass>
     </configuration>
          <executions>
               <execution>
                    <goals>
                         <goal>repackage</goal>
                    </goals>
               </execution>
          </executions>
  </plugin>
  <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
  </plugin>

核心插件maven-war-plugin

项目路径如下 spring boot CDN 项目
这个非常重要,有这个依赖,我们可以先用mvn运行gulp进行js css编译压缩和 版本+ CDN替换然后在调用war打包工具打包。做到偷梁换柱的作用。其中 prepare-package 类似于一个标记,会在 gulp编译的的时候用到,请继续下面篇文章,就会找到解答。

war打包原理

<plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
         <version>2.3</version>
         <executions>
              <execution>
                   <phase>prepare-package</phase>
                        <goals>
                            <goal>exploded</goal>
                        </goals>
                    </execution>
               </executions>
        <configuration>
        <webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
            <failOnMissingWebXml>false</failOnMissingWebXml>
            <useCache>true</useCache>
       /configuration>
</plugin>

添加gulp到 mvn中

项目路径如下 spring boot CDN 项目
prepare-package这个就是上面讲到的端点, 有了这个断点,mvn在打包的时候会先 执行gulp然后接着断点继续打war包

<profile>
            <id>prod</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.github.eirslett</groupId>
                        <artifactId>frontend-maven-plugin</artifactId>
                        <version>1.3</version>

                        <executions>
                            <execution>
                                <id>install node and npm</id>
                                <goals>
                                    <goal>install-node-and-npm</goal>
                                </goals>
                                <configuration>
                                    <nodeVersion>v6.6.0</nodeVersion>
                                    <npmVersion>3.10.3</npmVersion>
                                </configuration>
                            </execution>
                            <execution>
                                <id>npm install</id>
                                <goals>
                                    <goal>npm</goal>
                                </goals>
                                <configuration>
                                    <arguments>install</arguments>
                                </configuration>
                            </execution>
                            <execution>
                                <id>run gulp</id>
                                <phase>prepare-package</phase>
                                <goals>
                                    <goal>gulp</goal>
                                </goals>
                                <configuration>
                                    <arguments>cdnify</arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

gulp 分析

项目路径如下 spring boot CDN 项目

编译 sass --> css --> 文件合并 --> css文件压缩

项目路径如下 spring boot CDN 项目

gulp.task('convert-compress-sass', function(){
    return gulp.src('src/main/webapp/sass/*.scss')
        .pipe(sourceMap.init())
        .pipe(sass())
        .pipe(sourceMap.write('./'))
        .pipe(gulp.dest('src/main/webapp/app/styles/'));
});

js --> 合并 --> 格式校验

项目路径如下 spring boot CDN 项目

gulp.task('scripts', function () {
    return gulp.src('app/**/*.js', {cwd: 'src/main/webapp/'})
        .pipe(jshint())
        .pipe(jshint.reporter(stylish));
});

copy 字体

项目路径如下 spring boot CDN 项目
因为css 路径待会会加上CDN路径,因此CSS依赖的font路径也会变成CDN的路径,因此这时候需要把font单独拷贝出来。

gulp.task('copy-fonts', function () {
    return gulp.src(['src/main/webapp/bower_components/bootstrap/dist/fonts/*.{ttf,woff,woff2,eot,svg}'])
    // .pipe(flatten())
        .pipe(gulp.dest('target/spring-gulp-rev-cdn/static/fonts/'));
});

压缩jsp中的css和js

项目路径如下 spring boot CDN 项目
其中的 cssLibIndex cssAppIndex jsLibIndex appJs都是index.jsp中的

gulp.task('usemin', ['copy-fonts', 'scripts', 'convert-compress-sass'], function () {
    return gulp.src('**/*.jsp', {cwd: 'src/main/webapp/'})
        .pipe(useMin({
            cssLibIndex: [minifyCss({processImport: false})],
            cssAppIndex: [minifyCss()],
            jsLibIndex: [ngMin(), ugLify()],
            appJs: [ngMin(), ugLify().on('error', gulpUtil.log)]
        }))
        .pipe(gulp.dest('target/spring-gulp-rev-cdn/'));
});

打versin + 添加CDN路径

项目路径如下 spring boot CDN 项目


gulp.task('cdnify', ['usemin'], function () {
    var cssFilter = filter('**/*-all.css', {restore: true});
    var jsFilter = filter('**/*-all.js', {restore: true});
    return gulp.src(['target/spring-gulp-rev-cdn/static/js/*.js', 'target/spring-gulp-rev-cdn/static/styles/*.css', 'target/spring-gulp-rev-cdn/app/index.jsp'])
        .pipe(jsFilter)
        .pipe(rev())
        .pipe(jsFilter.restore)
        .pipe(gulp.dest('target/spring-gulp-rev-cdn/static/js/'))
        .pipe(cssFilter)
        .pipe(rev())
        .pipe(cssFilter.restore)
        .pipe(gulp.dest('target/spring-gulp-rev-cdn/static/styles/'))
        .pipe(revReplace({replaceInExtensions: ['.jsp']}))
        .pipe(cdnizer({
            defaultCDNBase: CDN ,
            relativeRoot: '/',
            files: [
                // {
                //     //ignore this file, otherwise it tries to map this to our cdn, which breaks the url
                //     file: 'http://g.alicdn.com/ilw/ding/0.8.6/scripts/dingtalk.js',
                //     cdn: 'http://g.alicdn.com/ilw/ding/0.8.6/scripts/dingtalk.js'
                // },
                '**/*-all-*.css',
                '**/lib-all-*.js',
                '**/app-all-*.js'
            ]}
        ))
        .pipe(gulp.dest("target/spring-gulp-rev-cdn/app/"));
});

到这里项目基本上结束了。

运行项目

mvn clean package spring-boot:repackage -Pprod
java -jar target/spring-gulp-rev-cdn.war
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
慷慨打赏