diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f96039 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e130c39 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,43 @@ +# Autodetect text files +* text=auto + +# ...Unless the name matches the following overriding patterns + +# Definitively text files +.* text eol=lf +*.php text eol=lf +*.css text eol=lf +*.js text eol=lf +*.html text eol=lf +*.json text eol=lf +*.less text eol=lf +*.scss text eol=lf +*.sass text eol=lf +*.txt text eol=lf +*.md text eol=lf +*.markdown text eol=lf +*.xml text eol=lf +*.json text eol=lf +*.bat text eol=lf +*.sh text eolf=lf +*.svg text eol=lf +*.sql text eol=lf +*.xml text eol=lf +*.yml text eol=lf + +# Ensure those won't be messed up with +*.ico binary +*.png binary +*.jpg binary +*.jpeg binary +*.webp binary +*.gif binary +*.eot binary +*.ttf binary +*.woff binary +*.woff2 binary +*.mp3 binary +*.m4a binary +*.mp4 binary +*.m4p binary +*.acc binary diff --git a/.gitignore b/.gitignore index 5148e52..788c9cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,12 @@ # Logs logs -*.log -npm-debug.log* +*.log* # Runtime data pids *.pid *.seed +*.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -35,3 +35,22 @@ jspm_packages # Optional REPL history .node_repl_history + +# gitkeep +!.gitkeep + +# IDE +.idea +*.iml + +# VSCode metadata +.vscode + +# Mac files +.DS_Store + +# Ignore minified files +*.min.* + +# Caches +.eslintcache diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..80fbbc9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +sudo: false + +language: node_js + +node_js: + - '7' + - '6' + - '5' + - '4' + +cache: + directories: + - node_modules + +before_install: + - npm prune + - npm update diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cac3786 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](http://semver.org/). + +# 0.0.1 - 2017-02-14 + +- Chore: initial public release. diff --git a/README.md b/README.md index 70ef096..94c6da2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,66 @@ # browser-sync-dev-hot-webpack-plugin -Combines BrowserSync, webpack-dev-middleware, and webpack-hot-middleware into one ezpz plugin. + +[![NPM version](https://img.shields.io/npm/v/browser-sync-dev-hot-webpack-plugin.svg)](https://www.npmjs.org/package/browser-sync-dev-hot-webpack-plugin) +[![Travis Build Status](https://img.shields.io/travis/itgalaxy/browser-sync-dev-hot-webpack-plugin/master.svg?label=build)](https://travis-ci.org/itgalaxy/browser-sync-dev-hot-webpack-plugin) +[![dependencies Status](https://david-dm.org/itgalaxy/browser-sync-dev-hot-webpack-plugin/status.svg)](https://david-dm.org/itgalaxy/browser-sync-dev-hot-webpack-plugin) +[![devDependencies Status](https://david-dm.org/itgalaxy/browser-sync-dev-hot-webpack-plugin/dev-status.svg)](https://david-dm.org/itgalaxy/browser-sync-dev-hot-webpack-plugin?type=dev) + +Combines BrowserSync, webpack-dev-middleware, and webpack-hot-middleware into one plugin. + +## Install + +```shell +npm install --save-dev browser-sync-dev-hot-webpack-plugin +``` + +## Usage + +```js +const BROWSER_SYNC_OPTIONS = {}; +const DEV_MIDDLEWARE_OPTIONS = { + publicPath: '/my/public/path' +}; +const HOT_MIDDLEWARE_OPTIONS = {}; + +const webpackConfig = { + // Some options... + plugins: [ + // Other plugins... + new BrowserSyncHotPlugin({ + browserSyncOptions: BROWSER_SYNC_OPTIONS, + devMiddlewareOptions: DEV_MIDDLEWARE_OPTIONS, + hotMiddlewareOptions: HOT_MIDDLEWARE_OPTIONS, + callback() { + console.log('Callback') + } + }) + // Other plugins... + ] + // Some options... +}; + +module.exports = webpackConfig; +``` + +## Options + +See related packages docs. + +## Related + +- [browser-sync](https://github.com/browsersync/browser-sync) - Keep multiple browsers & devices +in sync when building websites. + +- [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) - Offers a dev middleware for webpack, +which arguments a live bundle to a directory. + +- [webpack-hot-middleware](https://github.com/glenjamin/webpack-hot-middleware) - Webpack hot reloading +you can attach to your own server. + +## Contribution + +Feel free to push your code if you agree with publishing under the MIT license. + +## [Changelog](CHANGELOG.md) + +## [License](LICENSE) diff --git a/package.json b/package.json new file mode 100644 index 0000000..a919f55 --- /dev/null +++ b/package.json @@ -0,0 +1,86 @@ +{ + "name": "browser-sync-dev-hot-webpack-plugin", + "version": "0.0.1", + "description": "Combines BrowserSync, webpack-dev-middleware, and webpack-hot-middleware into one plugin", + "license": "MIT", + "author": "itgalaxy ", + "contributors": [ + { + "name": "Alexander Krasnoyarov", + "email": "alexander.krasnoyarov@itgalaxy.company", + "url": "https://vk.com/sterling_archer" + } + ], + "repository": { + "type": "https", + "url": "https://github.com/itgalaxy/browser-sync-dev-hot-webpack-plugin" + }, + "keywords": [ + "webpack", + "webpack-plugin", + "browsersync", + "browser-sync", + "livereload", + "serve", + "webpack-dev-middleware", + "webpack-hot-middleware" + ], + "bugs": { + "url": "https://github.com/itgalaxy/browser-sync-dev-hot-webpack-plugin/issues" + }, + "files": [ + "!**/__tests__" + ], + "main": "src/BrowserSyncDevHotWebpackPlugin.js", + "dependencies": { + "deepmerge": "^1.3.2" + }, + "devDependencies": { + "ajv-cli": "^1.1.0", + "eslint": "^3.15.0", + "eslint-plugin-ava": "^4.0.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-itgalaxy": "^38.0.0", + "eslint-plugin-jsx-a11y": "^4.0.0", + "eslint-plugin-lodash": "^2.1.0", + "eslint-plugin-node": "^4.0.0", + "eslint-plugin-promise": "^3.3.0", + "eslint-plugin-react": "^6.6.0", + "eslint-plugin-unicorn": "^2.0.0", + "npmpub": "^3.1.0", + "npm-run-all": "^4.0.0", + "package-schema": "^1.0.0", + "remark-cli": "^2.0.0", + "remark-lint": "^5.0.0", + "remark-preset-lint-itgalaxy": "^4.0.0" + }, + "peerDependencies": { + "browser-sync": "^2.0.0", + "webpack": "^1 || ^2 || ^2.0.0-beta || ^2.1.0-beta || ^2.2.0-rc.0", + "webpack-dev-middleware": "^1.0.0", + "webpack-hot-middleware": "^2.0.0" + }, + "scripts": { + "lint:eslint": "eslint . --ignore-path .gitignore --color", + "lint:package": "ajv -s ./node_modules/package-schema/schema.json -d package --errors=text", + "lint:remark": "remark . -i .gitignore -f -q", + "lint": "npm-run-all -l --parallel lint:*", + + "test": "npm run lint", + + "release": "npmpub" + }, + "eslintConfig": { + "rules": { + "strict": ["error", "global"] + }, + "parserOptions": { + "sourceType": "script" + }, + "extends": [ + "plugin:itgalaxy/esnext", + "plugin:itgalaxy/node" + ], + "root": true + } +} diff --git a/src/BrowserSyncDevHotWebpackPlugin.js b/src/BrowserSyncDevHotWebpackPlugin.js new file mode 100644 index 0000000..81f04bc --- /dev/null +++ b/src/BrowserSyncDevHotWebpackPlugin.js @@ -0,0 +1,99 @@ +'use strict'; + +/* eslint-disable node/no-missing-require */ +const webpackDevMiddleware = require('webpack-dev-middleware'); +const webpackHotMiddleware = require('webpack-hot-middleware'); +const browserSync = require('browser-sync'); +/* eslint-enable node/no-missing-require */ +const merge = require('deepmerge'); + +class BrowserSyncDevHotWebpackPlugin { + constructor(options) { + this.watcher = null; + this.compiler = null; + this.options = merge.all([ + { + browserSyncOptions: {}, + callback() {}, // eslint-disable-line no-empty-function + devMiddlewareOptions: { + noInfo: true, + stats: false + }, + hotMiddlewareOptions: {} + }, + options + ]); + } + + apply(compiler) { + if (this.options.disable) { + return; + } + + this.compiler = compiler; + + compiler.plugin('done', () => { + if (!this.watcher) { + this.watcher = browserSync.create(); + compiler.plugin('compilation', () => this.watcher.notify('Rebuilding...')); + this.start(); + } + }); + } + + start() { + let browserSyncURLLocal = 'initialization'; + let browserSyncURLExternal = 'initialization'; + let browserSyncURLUI = 'initialization'; + let browserSyncURLUIExternal = 'initialization'; + const watcherConfig = merge.all([ + { + proxy: { + middleware: this.middleware(), + proxyReq: [ + (proxyReq) => { + proxyReq.setHeader('X-Browser-Sync-URL-Local', browserSyncURLLocal); + proxyReq.setHeader('X-Browser-Sync-URL-External', browserSyncURLExternal); + proxyReq.setHeader('X-Browser-Sync-URL-UI', browserSyncURLUI); + proxyReq.setHeader('X-Browser-Sync-URL-UI-External', browserSyncURLUIExternal); + proxyReq.setHeader('X-Dev-Middleware', 'On'); + proxyReq.setHeader('X-Hot-Middleware', 'On'); + } + ] + } + }, + this.options.browserSyncOptions + ]); + + this.watcher.init(watcherConfig, (error, bs) => { + if (error) { + throw error; + } + + const URLs = bs.getOption('urls'); + + browserSyncURLLocal = URLs.get('local'); + browserSyncURLExternal = URLs.get('external'); + browserSyncURLUI = URLs.get('ui'); + browserSyncURLUIExternal = URLs.get('ui-external'); + + this.options.callback.bind(this); + }); + } + + middleware() { + const hotMiddlewareOptions = merge.all([ + { + log: this.watcher.notify.bind(this.watcher) + }, + this.options.hotMiddlewareOptions + ]); + + this.webpackDevMiddleware = webpackDevMiddleware(this.compiler, this.options.devMiddlewareOptions); + this.webpackHotMiddleware = webpackHotMiddleware(this.compiler, hotMiddlewareOptions); + + return [this.webpackDevMiddleware, this.webpackHotMiddleware]; + } +} + +module.exports = BrowserSyncDevHotWebpackPlugin;