diff --git a/.vuepress/config.js b/.vuepress/config.js
index 1ce0c9c..17dde62 100644
--- a/.vuepress/config.js
+++ b/.vuepress/config.js
@@ -17,6 +17,7 @@ module.exports = {
'/docs/styles.md',
'/docs/icons.md',
'/docs/utils.md',
+ '/docs/wordpress.md',
'/docs/extending.md',
]
}
diff --git a/docs/utils.md b/docs/utils.md
index bbe0e3e..9133c53 100644
--- a/docs/utils.md
+++ b/docs/utils.md
@@ -8,7 +8,11 @@ To configure them, you can pass these options in your `webpack.config.js`:
```typescript
features: {
styles: {
- browserSync?: boolean;
+ browserSync?: {
+ proxy: string;
+ host?: string;
+ port?: number;
+ };
jquery?: 'internal' | 'external';
}
}
@@ -26,8 +30,9 @@ BrowserSync seems to get around it by overriding paths in every HTML generated
by proxied site.
In this package, we use `browser-sync-webpack-plugin` to create BrowserSync
-instance which proxies our `webpack-dev-server`, which in turn proxies our
-WordPress site. Pretty complicated, but works! :tada:
+instance which proxies our WordPress site. Pretty complicated, but works! :tada:
+
+You can read more [here](wordpress.md).
## Difference between internal or external jQuery
@@ -40,7 +45,7 @@ done by `external` option here.
::: warning
-When using this option, please make sure that jQuery is loaded before webpack in
-HTML.
+When using this option, please make sure that jQuery is loaded before
+webpack-generated assets in HTML.
:::
diff --git a/docs/wordpress.md b/docs/wordpress.md
new file mode 100644
index 0000000..a2e8578
--- /dev/null
+++ b/docs/wordpress.md
@@ -0,0 +1,17 @@
+# Using with WordPress
+
+By default serving JS and CSS from `webpack-dev-server` does not work with
+WordPress due to absolute URL paths hardcoded in HTML. However,
+[BrowserSync](https://www.browsersync.io/) fixes this problem by replacing paths
+in HTML to proxied server. Because of that in WordPress we are using Webpack in
+watch mode (`webpack --watch`) with
+[`browser-sync-webpack-plugin`](https://github.com/Va1/browser-sync-webpack-plugin)
+enabled.
+
+There are few minor differences between this method and proxying with
+`webpack-dev-server`:
+
+* `webpack`-compiled assets are written to disk instead of memory,
+* BrowserSync doesn't reuse webpack-dev-server configuration, [so you have to
+ configure it in utils section](utils.md),
+* JS hot-reloading doesn't work (but CSS works).
diff --git a/package.json b/package.json
index 77e46c2..338c275 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.1.14",
+ "webpack-fix-style-only-entries": "^0.2.1",
"webpack-merge": "^4.2.1"
},
"devDependencies": {
diff --git a/src/@types/browser-sync-webpack-plugin.ts b/src/@types/browser-sync-webpack-plugin.ts
index 748c9b8..fc9e530 100644
--- a/src/@types/browser-sync-webpack-plugin.ts
+++ b/src/@types/browser-sync-webpack-plugin.ts
@@ -11,9 +11,9 @@ declare module 'browser-sync-webpack-plugin' {
}
namespace BrowserSyncPlugin {
interface IBrowserSyncOptions {
- host: string;
- port: number;
proxy: string;
+ host?: string;
+ port?: number;
}
interface IBrowserSyncPluginOptions {
diff --git a/src/@types/webpack-fix-style-only-entries.ts b/src/@types/webpack-fix-style-only-entries.ts
new file mode 100644
index 0000000..3da953e
--- /dev/null
+++ b/src/@types/webpack-fix-style-only-entries.ts
@@ -0,0 +1,19 @@
+///
+
+declare module 'webpack-fix-style-only-entries' {
+ import * as webpack from 'webpack';
+
+ class WebpackFixStyleOnlyEntries extends webpack.Plugin {
+ constructor(options?: WebpackFixStyleOnlyEntries.IOptions);
+ public apply(compiler: webpack.Compiler): void;
+ }
+
+ namespace WebpackFixStyleOnlyEntries {
+ interface IOptions {
+ extensions?: string[];
+ silent?: boolean;
+ }
+ }
+
+ export = WebpackFixStyleOnlyEntries;
+}
diff --git a/src/configs/styles.ts b/src/configs/styles.ts
index 2502a56..3caaee8 100644
--- a/src/configs/styles.ts
+++ b/src/configs/styles.ts
@@ -1,5 +1,6 @@
import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';
import * as magicImporter from 'node-sass-magic-importer';
+import * as FixStyleOnlyEntriesPlugin from 'webpack-fix-style-only-entries';
import { IConfiguration, WebpackMode } from '../defaultOptions';
@@ -19,26 +20,26 @@ export function styles({ styles: stylesConfig }: IConfiguration, mode: WebpackMo
const fileRegex = stylesConfig.scss ? /\.(sa|sc|c)ss$/ : /\.css$/;
const loaders = [
- stylesConfig.extractToFile && mode === 'production'
- ? MiniCssExtractPlugin.loader
- : 'style-loader',
+ stylesConfig.extractToFile
+ ? MiniCssExtractPlugin.loader
+ : 'style-loader',
'css-loader',
'resolve-url-loader',
];
const plugins = [];
+ plugins.push(new FixStyleOnlyEntriesPlugin());
+
if (stylesConfig.scss) {
loaders.push(sassLoader);
}
if (stylesConfig.extractToFile) {
- plugins.push(
- new MiniCssExtractPlugin({
- filename: '[name].css',
- chunkFilename: '[id].css',
- }),
- );
+ plugins.push(new MiniCssExtractPlugin({
+ filename: '[name].css',
+ chunkFilename: '[id].css',
+ }));
}
return {
diff --git a/src/configs/utils.ts b/src/configs/utils.ts
index dd17604..bf5de78 100644
--- a/src/configs/utils.ts
+++ b/src/configs/utils.ts
@@ -3,14 +3,14 @@ import { Configuration as WebpackConfiguration, ProvidePlugin } from 'webpack';
import { IConfiguration } from '../defaultOptions';
export interface IUtilOptions {
- browserSync?: boolean;
+ browserSync?: BrowserSyncPlugin.IBrowserSyncOptions;
jquery?: 'internal' | 'external';
}
function validateConfig(config: IUtilOptions) {
if (config.browserSync !== undefined) {
- if (typeof config.browserSync !== 'boolean') {
- throw new Error('Invalid option for browserSync, boolean should be passed.');
+ if (typeof config.browserSync !== 'object') {
+ throw new Error('Invalid option for browserSync, object should be passed.');
}
}
@@ -29,18 +29,9 @@ export function utils({ utils: utilsConfig }: IConfiguration) {
if (utilsConfig.browserSync) {
config.plugins = config.plugins || [];
- config.plugins.push(
- new BrowserSyncPlugin(
- {
- host: 'localhost',
- port: 3000,
- proxy: 'http://localhost:3100/',
- },
- {
- reload: false,
- },
- ),
- );
+ config.plugins.push(new BrowserSyncPlugin(utilsConfig.browserSync, {
+ reload: false,
+ }));
}
if (utilsConfig.jquery === 'external') {
diff --git a/src/configs/webpack.base.ts b/src/configs/webpack.base.ts
index 2d13713..6511860 100644
--- a/src/configs/webpack.base.ts
+++ b/src/configs/webpack.base.ts
@@ -7,7 +7,11 @@ const baseConfig = {
use: {
loader: 'babel-loader',
options: {
- presets: [['@babel/preset-env', { modules: false, useBuiltIns: 'usage' }]],
+ presets: [['@babel/preset-env', {
+ modules: false,
+ useBuiltIns: 'usage',
+ corejs: 2,
+ }]],
},
},
},
diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts
index 7969451..aac8e4c 100644
--- a/src/defaultOptions.ts
+++ b/src/defaultOptions.ts
@@ -22,7 +22,5 @@ export const defaultOptions: IConfiguration = {
extractToFile: true,
scss: true,
},
- utils: {
- browserSync: false,
- },
+ utils: {},
};
diff --git a/test/scss-glob/__snapshots__/test.spec.ts.snap b/test/scss-glob/__snapshots__/test.spec.ts.snap
index 22d4e82..f4b4b56 100644
--- a/test/scss-glob/__snapshots__/test.spec.ts.snap
+++ b/test/scss-glob/__snapshots__/test.spec.ts.snap
@@ -89,51 +89,6 @@ exports[`should import global scss files 1`] = `
/************************************************************************/
/******/ ({
-/***/ \\"./node_modules/css-loader/dist/cjs.js!./node_modules/resolve-url-loader/index.js!./node_modules/sass-loader/lib/loader.js?!./test/scss-glob/src/test.scss\\":
-/*!*****************************************************************************************************************************************************************!*\\\\
- !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js??ref--6-3!./test/scss-glob/src/test.scss ***!
- \\\\*****************************************************************************************************************************************************************/
-/*! no static exports found */
-/***/ (function(module, exports, __webpack_require__) {
-
-eval(\\"exports = module.exports = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ \\\\\\"./node_modules/css-loader/dist/runtime/api.js\\\\\\")(false);\\\\n// Module\\\\nexports.push([module.i, \\\\\\".first {\\\\\\\\n font-weight: bold; }\\\\\\\\n\\\\\\\\n.second {\\\\\\\\n color: #f0f; }\\\\\\\\n\\\\\\", \\\\\\"\\\\\\"]);\\\\n\\\\n\\\\n\\\\n//# sourceURL=webpack:///./test/scss-glob/src/test.scss?./node_modules/css-loader/dist/cjs.js!./node_modules/resolve-url-loader!./node_modules/sass-loader/lib/loader.js??ref--6-3\\");
-
-/***/ }),
-
-/***/ \\"./node_modules/css-loader/dist/runtime/api.js\\":
-/*!*****************************************************!*\\\\
- !*** ./node_modules/css-loader/dist/runtime/api.js ***!
- \\\\*****************************************************/
-/*! no static exports found */
-/***/ (function(module, exports, __webpack_require__) {
-
-\\"use strict\\";
-eval(\\"\\\\n\\\\n/*\\\\n MIT License http://www.opensource.org/licenses/mit-license.php\\\\n Author Tobias Koppers @sokra\\\\n*/\\\\n// css base code, injected by the css-loader\\\\nmodule.exports = function (useSourceMap) {\\\\n var list = []; // return the list of modules as css string\\\\n\\\\n list.toString = function toString() {\\\\n return this.map(function (item) {\\\\n var content = cssWithMappingToString(item, useSourceMap);\\\\n\\\\n if (item[2]) {\\\\n return '@media ' + item[2] + '{' + content + '}';\\\\n } else {\\\\n return content;\\\\n }\\\\n }).join('');\\\\n }; // import a list of modules into the list\\\\n\\\\n\\\\n list.i = function (modules, mediaQuery) {\\\\n if (typeof modules === 'string') {\\\\n modules = [[null, modules, '']];\\\\n }\\\\n\\\\n var alreadyImportedModules = {};\\\\n\\\\n for (var i = 0; i < this.length; i++) {\\\\n var id = this[i][0];\\\\n\\\\n if (id != null) {\\\\n alreadyImportedModules[id] = true;\\\\n }\\\\n }\\\\n\\\\n for (i = 0; i < modules.length; i++) {\\\\n var item = modules[i]; // skip already imported module\\\\n // this implementation is not 100% perfect for weird media query combinations\\\\n // when a module is imported multiple times with different media queries.\\\\n // I hope this will never occur (Hey this way we have smaller bundles)\\\\n\\\\n if (item[0] == null || !alreadyImportedModules[item[0]]) {\\\\n if (mediaQuery && !item[2]) {\\\\n item[2] = mediaQuery;\\\\n } else if (mediaQuery) {\\\\n item[2] = '(' + item[2] + ') and (' + mediaQuery + ')';\\\\n }\\\\n\\\\n list.push(item);\\\\n }\\\\n }\\\\n };\\\\n\\\\n return list;\\\\n};\\\\n\\\\nfunction cssWithMappingToString(item, useSourceMap) {\\\\n var content = item[1] || '';\\\\n var cssMapping = item[3];\\\\n\\\\n if (!cssMapping) {\\\\n return content;\\\\n }\\\\n\\\\n if (useSourceMap && typeof btoa === 'function') {\\\\n var sourceMapping = toComment(cssMapping);\\\\n var sourceURLs = cssMapping.sources.map(function (source) {\\\\n return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */';\\\\n });\\\\n return [content].concat(sourceURLs).concat([sourceMapping]).join('\\\\\\\\n');\\\\n }\\\\n\\\\n return [content].join('\\\\\\\\n');\\\\n} // Adapted from convert-source-map (MIT)\\\\n\\\\n\\\\nfunction toComment(sourceMap) {\\\\n // eslint-disable-next-line no-undef\\\\n var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\\\\n var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\\\\n return '/*# ' + data + ' */';\\\\n}\\\\n\\\\n//# sourceURL=webpack:///./node_modules/css-loader/dist/runtime/api.js?\\");
-
-/***/ }),
-
-/***/ \\"./node_modules/style-loader/lib/addStyles.js\\":
-/*!****************************************************!*\\\\
- !*** ./node_modules/style-loader/lib/addStyles.js ***!
- \\\\****************************************************/
-/*! no static exports found */
-/***/ (function(module, exports, __webpack_require__) {
-
-eval(\\"/*\\\\n\\\\tMIT License http://www.opensource.org/licenses/mit-license.php\\\\n\\\\tAuthor Tobias Koppers @sokra\\\\n*/\\\\n\\\\nvar stylesInDom = {};\\\\n\\\\nvar\\\\tmemoize = function (fn) {\\\\n\\\\tvar memo;\\\\n\\\\n\\\\treturn function () {\\\\n\\\\t\\\\tif (typeof memo === \\\\\\"undefined\\\\\\") memo = fn.apply(this, arguments);\\\\n\\\\t\\\\treturn memo;\\\\n\\\\t};\\\\n};\\\\n\\\\nvar isOldIE = memoize(function () {\\\\n\\\\t// Test for IE <= 9 as proposed by Browserhacks\\\\n\\\\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\\\\n\\\\t// Tests for existence of standard globals is to allow style-loader\\\\n\\\\t// to operate correctly into non-standard environments\\\\n\\\\t// @see https://github.com/webpack-contrib/style-loader/issues/177\\\\n\\\\treturn window && document && document.all && !window.atob;\\\\n});\\\\n\\\\nvar getTarget = function (target, parent) {\\\\n if (parent){\\\\n return parent.querySelector(target);\\\\n }\\\\n return document.querySelector(target);\\\\n};\\\\n\\\\nvar getElement = (function (fn) {\\\\n\\\\tvar memo = {};\\\\n\\\\n\\\\treturn function(target, parent) {\\\\n // If passing function in options, then use it for resolve \\\\\\"head\\\\\\" element.\\\\n // Useful for Shadow Root style i.e\\\\n // {\\\\n // insertInto: function () { return document.querySelector(\\\\\\"#foo\\\\\\").shadowRoot }\\\\n // }\\\\n if (typeof target === 'function') {\\\\n return target();\\\\n }\\\\n if (typeof memo[target] === \\\\\\"undefined\\\\\\") {\\\\n\\\\t\\\\t\\\\tvar styleTarget = getTarget.call(this, target, parent);\\\\n\\\\t\\\\t\\\\t// Special case to return head of iframe instead of iframe itself\\\\n\\\\t\\\\t\\\\tif (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\\\\n\\\\t\\\\t\\\\t\\\\ttry {\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t// This will throw an exception if access to iframe is blocked\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t// due to cross-origin restrictions\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tstyleTarget = styleTarget.contentDocument.head;\\\\n\\\\t\\\\t\\\\t\\\\t} catch(e) {\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tstyleTarget = null;\\\\n\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t\\\\tmemo[target] = styleTarget;\\\\n\\\\t\\\\t}\\\\n\\\\t\\\\treturn memo[target]\\\\n\\\\t};\\\\n})();\\\\n\\\\nvar singleton = null;\\\\nvar\\\\tsingletonCounter = 0;\\\\nvar\\\\tstylesInsertedAtTop = [];\\\\n\\\\nvar\\\\tfixUrls = __webpack_require__(/*! ./urls */ \\\\\\"./node_modules/style-loader/lib/urls.js\\\\\\");\\\\n\\\\nmodule.exports = function(list, options) {\\\\n\\\\tif (typeof DEBUG !== \\\\\\"undefined\\\\\\" && DEBUG) {\\\\n\\\\t\\\\tif (typeof document !== \\\\\\"object\\\\\\") throw new Error(\\\\\\"The style-loader cannot be used in a non-browser environment\\\\\\");\\\\n\\\\t}\\\\n\\\\n\\\\toptions = options || {};\\\\n\\\\n\\\\toptions.attrs = typeof options.attrs === \\\\\\"object\\\\\\" ? options.attrs : {};\\\\n\\\\n\\\\t// Force single-tag solution on IE6-9, which has a hard limit on the # of