Итак, моя компания работает над переводом своей кодовой базы внешнего интерфейса на платформу, подобную ReactJS.Мне было поручено разработать процесс сборки внешнего интерфейса с помощью веб-пакета 4. Прямо сейчас мне пока не нужно поддерживать React, поскольку мы реализуем это позже.Мне просто нужно заменить нашу текущую задачу сборки gulp на webpack 4. Я смог получить большую часть этой работы (HTML, SCSS, CSS, JS-компиляция).Проблема, с которой я продолжаю сталкиваться, заключается в том, чтобы веб-пакет знал о сгенерированном сервером контенте, в частности страницах JSP (Java Server Pages).Мне не нужно делать что-то необычное, я просто хочу, чтобы браузер автоматически перезагружался каждый раз, когда страница JSP сохраняется в обновленном виде.Я думаю, это будет возможно, так как наша текущая сборка GULP может сделать это без проблем.Я думаю, что это может иметь какое-то отношение только к Webpack, включая файлы, которые, как он знает, вам нужны.Я пробовал много разных конфигураций devServer, и я даже пытался использовать webpack-browsersync совместно и автономно от devServer.Файлы включены ниже.Любая помощь по этому вопросу будет принята с благодарностью!
package.json
{
"scripts": {
"dev": "node scripts/prepare.js && cross-env NODE_ENV=dev webpack-dev-server --progress --mode development --config webpack.dev.js && node scripts/cleanup.js",
"build": "node scripts/prepare.js && webpack -p --progress --mode production --config webpack.prod.js && node scripts/cleanup.js",
"test": "echo \"Error: no test specified\" && exit 1",
"stats": "webpack --config webpack.prod.js --profile --json > bundle-stats.json && node scripts/cleanup.js"
},
"devDependencies": {
"@babel/core": "^7.2.0",
"@babel/preset-env": "^7.2.0",
"@babel/preset-react": "^7.0.0",
"babel-eslint": "^8.2.6",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-env": "^1.7.0",
"browser-sync-webpack-plugin": "^2.2.2",
"concat-with-sourcemaps": "^1.1.0",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"expose-loader": "^0.7.5",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.5",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"raw-loader": "^1.0.0",
"sass-loader": "^7.1.0",
"uglify-js": "^3.4.9",
"uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"webpack-merge": "^4.1.5",
"webpack-visualizer-plugin": "^0.1.11",
"write-file-webpack-plugin": "^4.5.0"
},
"dependencies": {
"babel-loader": "^8.0.0",
"browser-sync": "^2.26.3",
"classlist-polyfill": "^1.2.0",
"element-closest": "^2.0.2",
"hammerjs": "^2.0.8",
"jquery": "^1.12.4",
"jquery-ui": "^1.12.1",
"js-cookie": "^2.2.0",
"lodash": "^4.17.10",
"owl.carousel": "^2.3.4",
"purecss-sass": "^1.0.0",
"slick-carousel": "^1.8.1"
}
}
constants.js
const path = require('path');
module.exports = {
//use path.resolve for better cross OS compatability
bases: {
src: path.resolve(__dirname, '..', 'web/webroot/WEB-INF/_ui-src'),
dist: path.resolve(__dirname, '..', 'web/webroot/_ui'),
common: path.resolve(__dirname, '..', 'web/webroot/WEB-INF/_ui-src/responsive/common'),
storefront: path.resolve(__dirname, '..'),
webinf: path.resolve(__dirname, '..', 'web/webroot/WEB-INF'),
views: path.resolve(__dirname, '..', 'web/webroot/WEB-INF/views')
}
};
webpack.common.js
const webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const constants = require('./scripts/constants');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const WriteFilePlugin = require('write-file-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// Is the current build a development build
const isDev = process.env.NODE_ENV === 'dev';
/**
* This returns an object that has the file path and name
* as the key and value of the items inside of it
* i.e. {'./responsive/common/js/file.js' : './responsive/common/js/file.js'}
* We then use the items in this object to build the path to the
* destination file so that it matches the directory structure of
* the source folders to assist with different themes
*/
const getEntry = () => {
let entry = {};
let distFilePath = '';
glob.sync(constants.bases.src + '/**/{bundle.js,pages/*.js,main.scss}').map(element => {
element = path.resolve(element);
distFilePath = getDistFilePath(element);
entry[distFilePath] = `.${element.replace(constants.bases.src, '')}`;
});
return entry;
};
/**
* Because we use a non-standard way of getting our entry files and
* mapping their output, sometimes we need to transform the output
* path. This handles the renaming of the output path for special cases.
* @param {string} filePath
*/
const getDistFilePath = filePath => {
filePath = `.${filePath.replace(`${constants.bases.src}`, '')}`;
//remap scss path so output matches path that .tag file expects
filePath = filePath.replace(
`${path.sep}scss${path.sep}main.scss`,
`${path.sep}css${path.sep}main.min`
);
return filePath;
};
module.exports = {
context: constants.bases.src,
entry: getEntry(),
output: {
filename: '[name]',
path: constants.bases.dist,
publicPath: '/_ui/'
},
resolve: {
alias: {
purecss: path.join(__dirname, '/node_modules/purecss-sass/vendor/assets/stylesheets/purecss')
}
},
optimization: {
minimizer: [
new UglifyJsPlugin({
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
]
},
plugins: [
new webpack.DefinePlugin({
isDev: isDev
}),
new webpack.ProvidePlugin({
'_.debounce': 'lodash/debounce',
'_.throttle': 'lodash/throttle'
}),
new MiniCssExtractPlugin({}),
new CopyWebpackPlugin([
{
from: `${constants.bases.common}/images/`,
to: `${constants.bases.dist}/responsive/common/images/[name].[ext]`,
toType: 'template',
debug: 'info'
},
{
from: `${constants.bases.src}/**/fonts/**/*`,
debug: 'info'
}
]),
new WriteFilePlugin()
],
module: {
rules: [
// Babel
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /(node_modules|bower_components)/,
options: {
compact: true
}
},
//create a global window object for jQuery
{
test: require.resolve('jquery'),
use: [
{ loader: 'expose-loader', options: '$' },
{ loader: 'expose-loader', options: 'jQuery' }
]
},
//create a global window object for js-cookie
{
test: require.resolve('js-cookie'),
use: [{ loader: 'expose-loader', options: 'Cookies' }]
},
// Styles
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
url: false,
sourceMap: isDev
}
},
{
loader: 'sass-loader',
options: {
sourceMap: isDev
}
}
]
}
]
}
};
webpack.dev.js
const merge = require('webpack-merge');
const Visualizer = require('webpack-visualizer-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const common = require('./webpack.common');
const constants = require('./scripts/constants');
module.exports = merge(common, {
devtool: 'cheap-source-map',
devServer: {
contentBase: constants.webinf,
watchContentBase: true,
host: '0.0.0.0',
https: true,
port: 3000,
stats: 'errors-only',
proxy: {
'/static/content': {
target: 'https://example.com',
secure: false
},
'/medias': {
target: 'https://example.com',
secure: false
},
'*': {
target: 'https://localhost:9002',
secure: false
}
},
// watchOptions: {
// aggregateTimeout: 300,
// ignored: /node_modules/,
// poll: true
// }
},
plugins: [
// new BrowserSyncPlugin(
// {
// host: '0.0.0.0',
// port: 3100,
// proxy: 'https://localhost:9002/',
// open: false,
// https: true,
// injectChanges: true,
// server: {
// baseDir: constants.webinf
// }
// }
// ),
new Visualizer({
filename: `../bundle-stats.html`
})
]
});
Структура файла (упрощенная версия)
webpack.common.js
webpack.dev.js
scripts/
- constants.js
web/
- webroot/
- WEB-INF/
- views/
- file.JSP << This is not causing an auto-reload even though the content-base on dev server points to all of WEB-INF/