美文网首页
传统JavaEE集成Vue

传统JavaEE集成Vue

作者: 赵贵阳_student | 来源:发表于2018-02-01 16:14 被阅读0次
    0.简介

    现在的开发都是讲究的是前后端的分离,但是有时候一些传统的老项目用的技术十分的不顺手,接下来讲一讲我是如何把Vue框架集成到老项目中去的

    1.项目环境配置:

    • 后端:SSH
    • 前端:npm,webpack vue全家桶

    首先来一个整个项目的截图

    传统项目的结构图

    想必大家对这个结构已经十分的了解了,这里简单的介绍下这个目录的结构:

    • .settings,.classpath,.project都是Eclipse里面的配置问你件
    • adf , res ,core,metedata 是关联的其他项目的源码
    • metedata是代码生成器
    • src 是以SSH为框架的后台代码
    • WebRoot是前端代码

    吐:下,这个就是老旧的JavaWeb项目,adf ,core,等都是引入的外部的的项目,这些东西是特喵的本可以打成jar包的!


    2.理清楚思路:

    来来来,先整理一下这个思路

    在整个项目中,我们最关心的问题就是这个开发的流程怎么走,首先,明确一下开发的流程:我这里采取从前到后的方式:即由一串url说起:如 http://127.0.0.1:8080/satellite_image//index/index.jsp ,这个是指向的是index.jsp,即index.jsp是整个页面的入口,index.jsp主要的功用是分为两个部分,1是通过域对象向jsp页面里面进行传值,而作为整个页面的容器,即承载html,那么此时的html和部署在ngix上的纯前端页面就没有什么区别了,我们只需要把npm相关配置文件丢在WebRoot的根目录下即可,说白了,就是整个把整个纯前端应用限制在了WebRoot这么个文件夹下

    前端需要分离的部分只能放到WebRoot下进行开发,开发的流程与传统的开发流程也没有实质性的区别:即是这样的,我们所有的jsp都要引入一个关键的*.js文件,作为整个文件的操作入口文件,然后再根据这个文件的模块,利用js模块化的思想和Vue模块化的思想将整个页面进行分隔,

    先上个图:


    重点关注的前端里面的东西

    build文件夹是存放编译之后的js文件,css是指样式文件,images是放置图片的,js是老旧项目原始的文件,懒得管了,js-es6才是我们的重头戏,重点编写的文件,其中api是用来搞数据操作交互的和其他操作,里面封装的Data.js就是重点通过ajax与服务器端的数据进行交互的,然后还有一些地图处理的api啊之类的,components是放置的Vue组件了,啊这些就是前端需要搞的知识点儿了,啊这里的就不详细介绍了,,我们重点关注的是流程的走通对不对,

    3.正文:

    其实吧,最重点的还是特喵的npm那一堆配置文件


    ,在实际开发的时候,在npm下就跑到Webroot目录下,跑npm run dev 即可以进行热重载的开发,用npm run build-product进行最终文件的压缩,混淆之类的.

    下面针对这些文件进行简单的介绍一下,先从npm的命令说起:

    看一下package.json这么文件,他是整个前端项目的核心组件和文件(复制过去记得把注释去掉):

    {
      "name": "mzb",  //项目的名称
      "version": "0.1.0",//版本号
      "private": true, //私有项目?
      "dependencies": { //项目中实打实需要用到的第三方插件,框架之类的,这些东西说白了,是项目的文件,或者是入口js文件需要用的,需要用的,会编译进去代码的
      "babel-runtime": "^6.26.0",//运行时,垫片库,貌似没有用到,它的作用是,配合通过babel-plugin-transform-runtime自动重写你的promise等原型对象。但是它不会模拟内置对象原型上的方法,比如Array-prototype.find,
      "es5-shim": "^4.5.10",//解决ie8以下的问题,这里投机了,由于入口文件都是import 而这个库只能用require,所以我编译了两次(*/ω\*),在编译完第一次之后,自动注入require('shim/eshim')然后再编译一次
      "sweetalert2": "^7.8.4",//甜美的弹出框
      "vue": "^2.5.13",//
      "vuex": "^3.0.1" //
      },
      "scripts": { // 输入 npm run 脚本时,所能执行的命令结合,在执行脚本的时候是可以指定一些参数的,相当于cmd中进行执行命令,多个命令之间用 && 进行分隔
      "test": "echo \"Error: no test specified\" && exit 1",
      "start": "webpack",//执行webpack的命令
      "server": "webpack-dev-server --open",
      "dev": "webpack-dev-server --devtool eval-source-map --progress --colors --hot --inline ", //执行热更新开发者模式
      "build": "webpack --config ./webpack.config.js --progress",
      "build-product": "Set NODE_ENV=production && webpack --config ./webpack.production.config.js --progress && npm run build-product-compatible-ie ",
      "build-product-compatible-ie": "webpack --config ./[webpack.compatible-ie.config.js](http://webpack.compatible-ie.config.js/) --progress"
      },
      "devDependencies": {//这些都是插件,说白了,是编译器需要用到的,是webpack.js需要用到的
      "babel-cli": "^6.26.0",//没用到
      "babel-core": "^6.26.0",//貌似和babel-profill有关,待研究
      "babel-loader": "^7.1.2",//必须要有的转码器啦
      "babel-plugin-transform-runtime": "^6.23.0",//配合上述的进行工作滴
      "babel-polyfill": "^6.26.0", //用于解决低版本浏览器api不全的问题,加入之后可以为所欲为的使用高级的api,在文件的头部统一使用 import 'babel-polyfill'
      "babel-preset-es2015": "^6.24.1",//转成es5的语法 配合bable-loader
      "babel-preset-es2015-loose": "^8.0.0",//es5语法的loose模式 配合bable-loader
      "babel-preset-latest": "^6.24.1",//当前阶段最新的语法 配合bable-loader
      "babel-preset-stage-3": "^6.24.1",//当前的语法 配合bable-loader
      "babel-register": "^6.26.0",//待研究,貌似没用到
      "babelify": "^7.3.0",//待研究,貌似没用到
      "compression-webpack-plugin": "^1.1.3",//gzip压缩插件
      "css-loader": "^0.28.7",//编译css文件的
      "es3ify-loader": "^0.2.0",//解决ie8-,主要是将访问方式统一抓变成object['prop']的形式
      "eslint-loader": "^1.9.0",//代码检查工具
      "style-loader": "^0.18.2",//编译样式文件和css-laoder配合,待研究
      "vue-loader": "^13.3.0",//编译*.vue组件的
      "vue-style-loader": "^3.0.1",//配合vue-laoder
      "vue-template-compiler": "^2.5.2",//配合vue-laoder
      "webpack": "^3.6.0",//打包工具啦
      "webpack-dev-server": "^1.14.1"//热更新用到的服务器啦
        }
    }
    

    详解开发模式下的webpack.config.js,即 执行npm run dev ,或者npm run build都发生了什么事情

    看文件.babelre

    {
    "presets": [["es2015",{"loose":false}],["stage-3"]], //指定转码时,代码所需要识别的高级语法有哪些
    "plugins": [     //转码插件
      "transform-runtime",//待研究
      "transform-es2015-classes"]//转es6里面的class语法,(其实吧,我觉得只用第一个就可以了,待研究)
    }
    

    看文件webpack.js

    //这里用到的就是nodejs里面的内容和语法了,遵循CommonJS的规范
    const path = require('path')
    const webpack = require('webpack'); //使用webpack自带的插件
    module.exports = {
    devtool: 'eval-source-map', //调试时使用的source map 方便快速查找文件
    entry: [
        "webpack-dev-server/client?[http://localhost:3000](http://localhost:3000/)",
        "webpack/hot/only-dev-server",
        __dirname + '/index/js-es6/index.js'
    ], //入口文件  【注意:__dirname 是node.js中的一个全局变量,它指向当前执行脚本所在的目录,故多用于构建工具的脚本中】
    output: {
        path: __dirname + '/index/build', //输出的路径
        filename: 'index.js' //输出的文件名
        // publicPath: '[http://localhost:3000/](http://localhost:3000/)'
    },
    module: { //多个依赖模块,如babel,react,laod等模块
        rules: [ //定义loader的规则,表示如何处理指定格式的拓展文件
            {
                test: /(\.js|\.jsx)$/,//解析的后缀
                use: {
                    loader: 'babel-loader'//解码器
                },
                exclude: /node_modules/ //自定哪些文件不搞
            },
            {
                test: /(\.css)$/,
                use: [
                    { loader: 'style-loader' },
                    {
                        loader: 'css-loader',
                        options: { modules: true }
                    }
                ]
            },
            {
                test: /(\.vue)$/,
                use: [
                    { loader: 'vue-loader' }
                ]
            }
        ]
    },
    resolve: { alias: { 'vue': 'vue/dist/vue.js' } },//这个是使用完整版,而不只是运行时的vue
    plugins: [new webpack.HotModuleReplacementPlugin()], //热加载插件
    devServer: {//这个就6了,这个是保证能在tomcat下,即同一个域下,实现热加载,在执行代理时,为保证符合代理的预期效果,可以到tomcat下把需要代理的文件删掉,目前也就只能代理的是这么个入口文件
        port: 3000, //代理服务器的端口
        proxy: {
            '**': {
                target: '[http://localhost:8080](http://localhost:8080/)', //代理的 服务器地址,
                secure: false,
                prependPath: false
            }
        },
        publicPath: '[http://localhost:3000/satellite_image/index/build/](http://localhost:3000/satellite_image/index/build/)',//代理的入口文件的地址,详细的路径呀
        historyApiFallback: true
      }
    }
    

    看文件webpack-inject-js-plugin.js

    /*
    在编译之后的脚本之后,往其头部添加一些引入的库
    用途:多用于连续打包,在下一次打包之前,引入必要的js库
    Author zgy
    */
    "use strict";
    const ConcatSource = require("webpack-sources").ConcatSource;
    const ModuleFilenameHelpers = require("./node_modules/webpack/lib/ModuleFilenameHelpers");
    const injectScript = (str) => {
        if (!str.includes("\n")) return `${str} \n`;
        return `${str.split("\n").join("\n  ")}\n`;
    };
    
    class InjectScript {
    constructor(options) {
        if (arguments.length > 1)
            throw new Error("脚本注入插件只能传入一个参数");
        if (typeof options.banner === "object") {
            options.banner = options.banner.map(item => `require('${item}');`).join('\n');
        }
        console.log(options.banner);
        if (typeof options === "string")
            options = {
                banner: `require('${options}')`
            };
        this.options = options || {};
        this.banner = this.options.raw ? options.banner : injectScript(options.banner);
        console.log(this.banner);
    }
    apply(compiler) {
        const options = this.options;
        const banner = this.banner;
        console.log("apply-->"+banner);
        compiler.plugin("compilation", (compilation) => {
            compilation.plugin("optimize-chunk-assets", (chunks, callback) => {
                chunks.forEach((chunk) => {
                    if (options.entryOnly && !chunk.isInitial()) return;
                    chunk.files
                        .filter(ModuleFilenameHelpers.matchObject.bind(undefined, options))
                        .forEach((file) => {
                            let basename;
                            let query = "";
                            let filename = file;
                            const hash = compilation.hash;
                            const querySplit = filename.indexOf("?");
                            if (querySplit >= 0) {
                                query = filename.substr(querySplit);
                                filename = filename.substr(0, querySplit);
                            }
                            if (filename.indexOf("/") < 0) {
                                basename = filename;
                            } else {
                                basename = filename.substr(filename.lastIndexOf("/") + 1);
                            }
                            const comment = compilation.getPath(banner, {
                                hash,
                                chunk,
                                filename,
                                basename,
                                query,
                            });
                            console.log("apply-->comment-->"+comment);
                            console.log("apply-->file-->"+compilation.assets[file]);
                            return compilation.assets[file] = new ConcatSource(comment, "\n", compilation.assets[file]);
                        });
                });
                callback();
            });
        });
      }
    }
    module.exports = InjectScript;
    

    看文件npm run build-product 发生了什么,重头戏,webpack.compatible-ie.config.js和webpack.production.config.js

    看文件webpack.production.config.js

    // webpack.production.config.js
    const webpack = require('webpack');
    const InjectScript = require('./webpack-inject-js-plugin.js');
    module.exports = {
    entry: [
        __dirname + '/index/js-es6/index.js'
    ], //入口文件  【注意:__dirname 是node.js中的一个全局变量,它指向当前执行脚本所在的目录,故多用于构建工具的脚本中】
    output: {
        path: __dirname + '/index/build', //输出的路径
        filename: 'index.js' //输出的文件名
    },
    module: {
        rules: [{
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            // {
            //     test: /(\.js)$/,
            //     use: {
            //         loader: 'es3ify-loader',
            //     }
            // },
            {
                test: /(\.vue)$/,
                use: [
                    { loader: 'vue-loader' }
                ]
            }
        ]
    },
    plugins: [
        // new webpack.optimize.OccurrenceOrderPlugin(),
        /*
         *目前需要解决的是ie中的Object.defineProperty,根据[http://www.aliued.com/?p=3240](http://www.aliued.com/?p=3240) ,暂用得解决方案是转码再转码
         *即先webpack转码一次通用的.js文件,然后注入脚本require('es5-shim')等包,再进行另外一次webpack进行打包转码
         */
        // new InjectScript({banner:['es5-shim','es5-shim/es5-sham']}),//处理es9以下的浏览器api问题,兼容ie9暂时不用
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({ //混淆插件,其实如果不去兼容ie的即使用 InjectScript注入插件,则可以直接和下面这个文件的内容进行合并
            compress: {
                properties: false,
                warnings: false
            },
            output: {
                beautify: true,
                quote_keys: true
            },
            mangle: {
                screw_ie8: false
            },
            sourceMap: false
        })
        ///配置在了Comatible-ie-config.js里面了
        // new CompressionWebpackPlugin({ //gzip 压缩
        //     asset: '[path].gz[query]',
        //     algorithm: 'gzip',
        //     test: new RegExp(
        //         '\\.(js|css)$' //压缩 js 与 css
        //     ),
        //     threshold: 10240,
        //     minRatio: 0.8
        // })
    ],
      resolve: { alias: { 'vue': 'vue/dist/vue.min.js' } }
     };
    

    webpack.compatible-ie.config.js,其实如不要使用注入引入的插件,则不要这样子搞,合并即可

    //其实这个文件才是最后执行的,哈!

    // webpack.production.config.js
    const webpack = require('webpack');
    const CompressionWebpackPlugin = require('compression-webpack-plugin');
    module.exports = {
    entry: [
        __dirname + '/index/build/index.js'
    ], //入口文件  【注意:__dirname 是node.js中的一个全局变量,它指向当前执行脚本所在的目录,故多用于构建工具的脚本中】
    output: {
        path: __dirname + '/index/build', //输出的路径
        filename: 'index.js' //输出的文件名
    },
    module: {
        rules: [
            {
                test: /(\.js)$/,
                use: {
                    loader: 'es3ify-loader',
                }
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
        // new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                properties: false,
                warnings: false
            },
            output: {
                beautify: false,
                quote_keys: true
            },
            mangle: {
                screw_ie8: false
            },
            sourceMap: false
        }),
                ///配置在了Comatible-ie-config.js里面了
        new CompressionWebpackPlugin({ //gzip 压缩
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            filename(oldFileName){
                // 符合公司框架的解析规则
                return oldFileName.substring(0,oldFileName.indexOf("."))+".gzjs";
            },
            test: new RegExp(
                '\\.(js|css)$' //压缩 js 与 css
            ),
            threshold: 10240,
            minRatio: 0.8
        })
    ]
    };
    

    综上所述,以上的开发流程是这样子的

    1. 首先新建传统的javaeb项目,maven也可以啦
    2. 在WebRoot下部署node环境,即编写上述的那些个包之类的,是实际的项目发布时,是不需要/node_moudle/这个文件夹的
    3. 建立入口html或者jsp
    4. 新建入口.js,记得抽出一个文件单独处理与服务器的数据交互工作
    5. 在html中引入这个编译之后的入口文件,入口引入的方式不同,热加载的方式也不同,即webServer中,publicPath需要变一变
    6. 编写webpack的配置文件,指定入口出口文件啊,配置webserver等
    7. 在实际部署时,一定要记得跑product.config,让js文件该压缩的压缩,该混淆的混淆

    其实上面的那些不看也可以!

    • 第一步:把这些npm相关的文件丢到webroot目录下

    • 第二步:配置好jsp里面的入口*.js

    • 第三步,修改webpack.config里面的入口出口参数,

    • 第四步:到WebRoot目录下:执行npm run dev,部署的时候执行npm run build-product

    相关文章

      网友评论

          本文标题:传统JavaEE集成Vue

          本文链接:https://www.haomeiwen.com/subject/bqgdzxtx.html