Liferay DXP 前端热部署
Liferay DXP Frontend Hot Deployment
我想对某些 Portlet 的前端代码(HTML、CSS、JS)进行热部署,这样可以节省开发时间而不是整个 Portlet需要重新部署。
Portlet 是一个 .war 文件。
在旧的 Liferay 6.2 中,这可以通过覆盖 tomcat/webapps/portlet-name
目录中的静态前端代码来实现。
在 Liferay DXP 中,这不再可能,因为 Portlet 不再被提取到 tomcat/webapps/
。
前端热部署有没有可能,所以我可以改变,例如我的 .html 文件正在运行,我不必重新部署整个 .war Portlet?
除了所描述的方法是 非常糟糕的维护做法 之外,我想知道您实际节省了多少时间(正如您所说,这是您的动机)。
您总是可以实施您的 portlet 以包含来自 Liferay 控制之外的地方的各种资源,但自然地,所提供的工具不会帮助您保持一切同步 - 这将是您需要解决的个人问题。
顺便说一下:Tomcat 的模式,在这种模式下,您可以只替换 webapps 目录中的随机内容,称为 development 模式。
我们找到了一个替代解决方案来缩短我们的前端开发时间,但它的工作原理与旧 Liferay 6.2 中的完全不同。
基本上我们使用一个 express.js 代理服务器,它在一些不同的端口上与 Liferay 并行运行。此代理服务器将所有请求转发给其他 运行 liferay,但对 HTML、CSS 和 JS 文件的请求除外。这些是直接从本地文件系统提供的。当 HTML、CSS 或 JS 文件被更改和保存时,也会触发前端的自动重建。
这个小 Proxy-Server 基本上由这两个文件组成:
dev-server.js 文件:
const packageConfig = require('../../../package.json');
const projectName = packageConfig.name;
const config = Object.assign({}, {
port: 8088,
liferayUrl: 'http://localhost:8080',
liferayVersion: 7,
webpackConfigFile: './webpack.development.config.js',
}, packageConfig.devServer || {});
const path = require('path');
const webpack = require('webpack');
const middleware = require('webpack-dev-middleware');
const webpackCompiler = webpack(require(config.webpackConfigFile));
const express = require('express');
const app = express();
const httpProxy = require('http-proxy');
const liferayProxy = httpProxy.createProxyServer();
let publicPath = `/o/${projectName}/static/js/`;
if(config.liferayVersion === 6) {
publicPath = `/${projectName}/static/js/`
}
app.use(
middleware(webpackCompiler, {
publicPath: `/o/${projectName}/static/js/`
})
);
app.all('/*', function(req, res) {
liferayProxy.web(req, res, {target: config.liferayUrl});
});
app.listen(config.port, () => console.log('Development server listening on port ' + config.port + '!'));
和package.json:
{
"name": "react-base",
"version": "1.0.0",
"license": "NOLICENSE",
"private": true,
"scripts": {
"preinstall": "node ./target/ui-build/build/preInstallHook.js",
"build-dev": "gulp --gulpfile ./target/ui-build/build/gulpfile.js && webpack --config ./target/ui-build/build/webpack.development.config.js --progress --profile",
"build": "gulp --gulpfile ./target/ui-build/build/gulpfile.js production && webpack --config ./target/ui-build/build/webpack.production.config.js --bail",
"lint": "eslint -c ./target/ui-build/build/.eslintrc.js --rulesdir \"node_modules/@myproject/react-component-lib/eslint-rules/\" \"src/main/react/**/*.js\" ",
"test": "jest --config=./target/ui-build/build/jest.config.js --rootDir=./ --passWithNoTests",
"coverage": "jest --config=./target/ui-build/build/jest.config.js --rootDir=./ --passWithNoTests --coverage",
"stats": "webpack-bundle-analyzer ./target/generated-sources/js/stats.json",
"start:dev": "node ./target/ui-build/build/dev-server.js"
},
"dependencies": {
"@babel/runtime": "^7.0.0",
"mobx": "3.1.16",
"mobx-react": "4.4.3",
"prop-types": "15.7.2",
"react": "16.8.4",
"react-dom": "16.8.4"
},
"devDependencies": {
"autoprefixer": "^9.1.5",
"babel-core": "^7.0.0-bridge.0",
"@babel/core": "7.1.0",
"babel-eslint": "10.0.1",
"babel-jest": "^23.0.0",
"babel-loader": "8.0.4",
"@babel/plugin-proposal-class-properties": "7.1.0",
"@babel/plugin-proposal-decorators": "7.1.0",
"@babel/plugin-proposal-object-rest-spread": "7.0.0",
"@babel/plugin-transform-runtime": "7.1.0",
"@babel/preset-env": "7.1.0",
"@babel/preset-react": "7.0.0",
"css-loader": "1.0.0",
"enzyme": "3.4.0",
"enzyme-adapter-react-16": "1.5.0",
"eslint": "4.19.1",
"eslint-plugin-jsx-a11y": "6.0.3",
"eslint-plugin-react": "7.11.1",
"express": "4.17.1",
"file-loader": "2.0.0",
"fs-extra": "7.0.0",
"gulp": "3.9.1",
"gulp-concat": "2.6.1",
"http-proxy": "1.17.0",
"identity-obj-proxy": "3.0.0",
"jest": "^23.0.0",
"jest-cli": "^23.0.0",
"node-sass": "4.9.3",
"postcss-loader": "3.0.0",
"raf": "3.4.1",
"react-test-renderer": "16.8.4",
"run-sequence": "1.2.2",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"url-loader": "1.1.2",
"url-search-params-polyfill": "5.0.0",
"webpack": "4.20.2",
"webpack-bundle-analyzer": "^3.0.2",
"webpack-cli": "^3.1.1",
"webpack-dev-middleware": "3.7.0"
},
"sideEffects": [
"*.css",
"*.scss"
]
}
Proxy-Server可以通过调用'yarn run start:dev'启动,然后你可以通过Proxy-Server通过http://localhost:8088
访问Liferay
我想对某些 Portlet 的前端代码(HTML、CSS、JS)进行热部署,这样可以节省开发时间而不是整个 Portlet需要重新部署。
Portlet 是一个 .war 文件。
在旧的 Liferay 6.2 中,这可以通过覆盖 tomcat/webapps/portlet-name
目录中的静态前端代码来实现。
在 Liferay DXP 中,这不再可能,因为 Portlet 不再被提取到 tomcat/webapps/
。
前端热部署有没有可能,所以我可以改变,例如我的 .html 文件正在运行,我不必重新部署整个 .war Portlet?
除了所描述的方法是 非常糟糕的维护做法 之外,我想知道您实际节省了多少时间(正如您所说,这是您的动机)。
您总是可以实施您的 portlet 以包含来自 Liferay 控制之外的地方的各种资源,但自然地,所提供的工具不会帮助您保持一切同步 - 这将是您需要解决的个人问题。
顺便说一下:Tomcat 的模式,在这种模式下,您可以只替换 webapps 目录中的随机内容,称为 development 模式。
我们找到了一个替代解决方案来缩短我们的前端开发时间,但它的工作原理与旧 Liferay 6.2 中的完全不同。
基本上我们使用一个 express.js 代理服务器,它在一些不同的端口上与 Liferay 并行运行。此代理服务器将所有请求转发给其他 运行 liferay,但对 HTML、CSS 和 JS 文件的请求除外。这些是直接从本地文件系统提供的。当 HTML、CSS 或 JS 文件被更改和保存时,也会触发前端的自动重建。
这个小 Proxy-Server 基本上由这两个文件组成:
dev-server.js 文件:
const packageConfig = require('../../../package.json');
const projectName = packageConfig.name;
const config = Object.assign({}, {
port: 8088,
liferayUrl: 'http://localhost:8080',
liferayVersion: 7,
webpackConfigFile: './webpack.development.config.js',
}, packageConfig.devServer || {});
const path = require('path');
const webpack = require('webpack');
const middleware = require('webpack-dev-middleware');
const webpackCompiler = webpack(require(config.webpackConfigFile));
const express = require('express');
const app = express();
const httpProxy = require('http-proxy');
const liferayProxy = httpProxy.createProxyServer();
let publicPath = `/o/${projectName}/static/js/`;
if(config.liferayVersion === 6) {
publicPath = `/${projectName}/static/js/`
}
app.use(
middleware(webpackCompiler, {
publicPath: `/o/${projectName}/static/js/`
})
);
app.all('/*', function(req, res) {
liferayProxy.web(req, res, {target: config.liferayUrl});
});
app.listen(config.port, () => console.log('Development server listening on port ' + config.port + '!'));
和package.json:
{
"name": "react-base",
"version": "1.0.0",
"license": "NOLICENSE",
"private": true,
"scripts": {
"preinstall": "node ./target/ui-build/build/preInstallHook.js",
"build-dev": "gulp --gulpfile ./target/ui-build/build/gulpfile.js && webpack --config ./target/ui-build/build/webpack.development.config.js --progress --profile",
"build": "gulp --gulpfile ./target/ui-build/build/gulpfile.js production && webpack --config ./target/ui-build/build/webpack.production.config.js --bail",
"lint": "eslint -c ./target/ui-build/build/.eslintrc.js --rulesdir \"node_modules/@myproject/react-component-lib/eslint-rules/\" \"src/main/react/**/*.js\" ",
"test": "jest --config=./target/ui-build/build/jest.config.js --rootDir=./ --passWithNoTests",
"coverage": "jest --config=./target/ui-build/build/jest.config.js --rootDir=./ --passWithNoTests --coverage",
"stats": "webpack-bundle-analyzer ./target/generated-sources/js/stats.json",
"start:dev": "node ./target/ui-build/build/dev-server.js"
},
"dependencies": {
"@babel/runtime": "^7.0.0",
"mobx": "3.1.16",
"mobx-react": "4.4.3",
"prop-types": "15.7.2",
"react": "16.8.4",
"react-dom": "16.8.4"
},
"devDependencies": {
"autoprefixer": "^9.1.5",
"babel-core": "^7.0.0-bridge.0",
"@babel/core": "7.1.0",
"babel-eslint": "10.0.1",
"babel-jest": "^23.0.0",
"babel-loader": "8.0.4",
"@babel/plugin-proposal-class-properties": "7.1.0",
"@babel/plugin-proposal-decorators": "7.1.0",
"@babel/plugin-proposal-object-rest-spread": "7.0.0",
"@babel/plugin-transform-runtime": "7.1.0",
"@babel/preset-env": "7.1.0",
"@babel/preset-react": "7.0.0",
"css-loader": "1.0.0",
"enzyme": "3.4.0",
"enzyme-adapter-react-16": "1.5.0",
"eslint": "4.19.1",
"eslint-plugin-jsx-a11y": "6.0.3",
"eslint-plugin-react": "7.11.1",
"express": "4.17.1",
"file-loader": "2.0.0",
"fs-extra": "7.0.0",
"gulp": "3.9.1",
"gulp-concat": "2.6.1",
"http-proxy": "1.17.0",
"identity-obj-proxy": "3.0.0",
"jest": "^23.0.0",
"jest-cli": "^23.0.0",
"node-sass": "4.9.3",
"postcss-loader": "3.0.0",
"raf": "3.4.1",
"react-test-renderer": "16.8.4",
"run-sequence": "1.2.2",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"url-loader": "1.1.2",
"url-search-params-polyfill": "5.0.0",
"webpack": "4.20.2",
"webpack-bundle-analyzer": "^3.0.2",
"webpack-cli": "^3.1.1",
"webpack-dev-middleware": "3.7.0"
},
"sideEffects": [
"*.css",
"*.scss"
]
}
Proxy-Server可以通过调用'yarn run start:dev'启动,然后你可以通过Proxy-Server通过http://localhost:8088
访问Liferay