Webpack 4 - devServer не загружается автоматически при обновлении файлов JSP - PullRequest
0 голосов
/ 13 декабря 2018

Итак, моя компания работает над переводом своей кодовой базы внешнего интерфейса на платформу, подобную 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/ 

1 Ответ

0 голосов
/ 14 декабря 2018

В заключение, я не верю, что есть способ заставить Webpack 4 наблюдать за вашим JSP (или другими страницами, сгенерированными сервером) из коробки, потому что они нигде не требуются / не импортируются, поэтому Webpack не знает о них(поправьте меня если я ошибаюсь).Я наткнулся на внешний плагин под названием ExtraWatchWebpackPlugin .Вы можете указать дополнительные каталоги или файлы для просмотра devServer или BrowserSync.Мой новый файл webpack.dev.js выглядит так:

const merge = require('webpack-merge');
const Visualizer = require('webpack-visualizer-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-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,
    //   poll: true,
    ignored: /node_modules/
    }
  },
  plugins: [
    // new BrowserSyncPlugin(
    //   {
    //     host: '0.0.0.0',
    //     port: 3100,
    //     proxy: 'https://localhost:9002/',
    //     open: false,
    //     https: true,
    //     injectChanges: true,
    //   }
    // ),
    new ExtraWatchWebpackPlugin({
      dirs: [constants.bases.views]
    }),
    new Visualizer({
      filename: `../bundle-stats.html`
    })
  ]
});
...