├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENCE ├── README.md ├── index.js ├── lib ├── BrowserSyncPlugin.js └── getCssOnlyEmittedAssetsNames.js ├── package-lock.json └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | indent_style = space 11 | 12 | [*.{js,json,md}] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .DS_Store 3 | *.log 4 | *.swp 5 | node_modules/ 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .DS_Store 3 | *.log 4 | *.swp 5 | node_modules/ 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Valentyn Barmashyn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [BrowserSync](https://browsersync.io/) plugin for [Webpack](https://webpack.js.org/) 2 | 3 | Easily use BrowserSync in your Webpack project. 4 | 5 | ## Install: 6 | 7 | ```bash 8 | $ npm install --save-dev browser-sync-webpack-plugin 9 | ``` 10 | or 11 | ```bash 12 | $ yarn add --dev browser-sync-webpack-plugin 13 | ``` 14 | 15 | With release of 2.0.0 the plugin is expected to be used in Node v4+ environment. 16 | Support for Node v3 and lower was dropped, but you can install and use the plugin version of 1.2.0 in older environments. 17 | 18 | ## Usage: 19 | 20 | BrowserSync will start only when you run Webpack in [watch mode](http://webpack.github.io/docs/tutorials/getting-started/#watch-mode): 21 | 22 | ```bash 23 | $ webpack --watch 24 | ``` 25 | 26 | ### Basic: 27 | 28 | If you're not using Webpack Dev Server, you can make BrowserSync to serve your project. 29 | The setup is pretty easy: just pass the [BrowserSync options](http://www.browsersync.io/docs/options/) to the plugin as the first argument. 30 | 31 | In your `webpack.config.js`: 32 | 33 | ```javascript 34 | const BrowserSyncPlugin = require('browser-sync-webpack-plugin') 35 | 36 | module.exports = { 37 | // ... 38 | plugins: [ 39 | new BrowserSyncPlugin({ 40 | // browse to http://localhost:3000/ during development, 41 | // ./public directory is being served 42 | host: 'localhost', 43 | port: 3000, 44 | server: { baseDir: ['public'] } 45 | }) 46 | ] 47 | } 48 | ``` 49 | 50 | ### Advanced: 51 | 52 | The advanced usage is about using [Webpack Dev Server](https://github.com/webpack/webpack-dev-server) with BrowserSync in order to use awesome features of both. 53 | 54 | To achieve this, BrowserSync offers the [proxy](http://www.browsersync.io/docs/options/#option-proxy) option. 55 | So, basically, you are about to proxy the output from the Webpack Dev Server through BrowserSync to get the best out of both. 56 | 57 | In your `webpack.config.js`: 58 | 59 | ```javascript 60 | const BrowserSyncPlugin = require('browser-sync-webpack-plugin') 61 | 62 | module.exports = { 63 | // ... 64 | plugins: [ 65 | new BrowserSyncPlugin( 66 | // BrowserSync options 67 | { 68 | // browse to http://localhost:3000/ during development 69 | host: 'localhost', 70 | port: 3000, 71 | // proxy the Webpack Dev Server endpoint 72 | // (which should be serving on http://localhost:3100/) 73 | // through BrowserSync 74 | proxy: 'http://localhost:3100/' 75 | }, 76 | // plugin options 77 | { 78 | // prevent BrowserSync from reloading the page 79 | // and let Webpack Dev Server take care of this 80 | reload: false 81 | } 82 | ) 83 | ] 84 | } 85 | ``` 86 | 87 | --- 88 | 89 | Other supported plugin options are: 90 | 91 | * `name` - default: `bs-webpack-plugin`, BrowserSync [instance name](http://www.browsersync.io/docs/api/#api-name) 92 | * `callback` - default: `undefined`, BrowserSync [instance init callback](http://www.browsersync.io/docs/api/#api-cb). 93 | * `injectCss` - default: `false`, allows BrowserSync to inject changes inplace instead of reloading the page when changed chunks are all CSS files 94 | 95 | ## Contributing: 96 | 97 | Feel free to open issues to propose stuff and participate. Pull requests are also welcome. 98 | 99 | ## Licence: 100 | 101 | [MIT](http://en.wikipedia.org/wiki/MIT_License) 102 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const BrowserSyncPlugin = require('./lib/BrowserSyncPlugin') 2 | 3 | module.exports = BrowserSyncPlugin 4 | -------------------------------------------------------------------------------- /lib/BrowserSyncPlugin.js: -------------------------------------------------------------------------------- 1 | const browserSync = require('browser-sync') 2 | const getCssOnlyEmittedAssetsNames = require('./getCssOnlyEmittedAssetsNames') 3 | 4 | const defaultPluginOptions = { 5 | reload: true, 6 | name: 'bs-webpack-plugin', 7 | callback: undefined, 8 | injectCss: false 9 | } 10 | 11 | class BrowserSyncPlugin { 12 | constructor (browserSyncOptions, pluginOptions) { 13 | this.browserSyncOptions = Object.assign({}, browserSyncOptions) 14 | this.options = Object.assign({}, defaultPluginOptions, pluginOptions) 15 | 16 | this.browserSync = browserSync.create(this.options.name) 17 | this.isWebpackWatching = false 18 | this.isBrowserSyncRunning = false 19 | } 20 | 21 | apply (compiler) { 22 | const watchRunCallback = () => { 23 | this.isWebpackWatching = true 24 | } 25 | const compilationCallback = () => { 26 | if (this.isBrowserSyncRunning && this.browserSyncOptions.notify) { 27 | this.browserSync.notify('Rebuilding...') 28 | } 29 | } 30 | const doneCallback = stats => { 31 | if (!this.isWebpackWatching) { 32 | return 33 | } 34 | 35 | if (!this.isBrowserSyncRunning) { 36 | this.browserSync.init(this.browserSyncOptions, this.options.callback) 37 | this.isBrowserSyncRunning = true 38 | } 39 | 40 | if (this.options.reload && this.browserSync.active) { 41 | this.browserSync.reload(this.options.injectCss && getCssOnlyEmittedAssetsNames(stats)) 42 | } 43 | } 44 | 45 | if (typeof compiler.hooks !== 'undefined') { 46 | compiler.hooks.watchRun.tap(BrowserSyncPlugin.name, watchRunCallback) 47 | compiler.hooks.compilation.tap(BrowserSyncPlugin.name, compilationCallback) 48 | compiler.hooks.done.tap(BrowserSyncPlugin.name, doneCallback) 49 | } else { 50 | compiler.plugin('watch-run', (watching, callback) => { 51 | watchRunCallback() 52 | callback(null, null) 53 | }) 54 | compiler.plugin('compilation', compilationCallback) 55 | compiler.plugin('done', doneCallback) 56 | } 57 | } 58 | } 59 | 60 | module.exports = BrowserSyncPlugin 61 | -------------------------------------------------------------------------------- /lib/getCssOnlyEmittedAssetsNames.js: -------------------------------------------------------------------------------- 1 | const { get } = require('lodash') 2 | 3 | function getCssOnlyEmittedAssetsNames (stats) { 4 | const assetsStatsMapping = get(stats, 'compilation.assets', {}) 5 | const assetsNames = Object.keys(assetsStatsMapping) 6 | const emittedAssetsNames = assetsNames.filter(assetName => get(assetsStatsMapping, [assetName, 'emitted'], false)) 7 | const isCssOnlyEmission = emittedAssetsNames.every(assetName => assetName.includes('.css')) 8 | 9 | return isCssOnlyEmission && emittedAssetsNames 10 | } 11 | 12 | module.exports = getCssOnlyEmittedAssetsNames 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browser-sync-webpack-plugin", 3 | "version": "2.4.0", 4 | "description": "BrowserSync and Webpack integration", 5 | "keywords": [ 6 | "webpack", 7 | "webpack-plugin", 8 | "browsersync", 9 | "browser-sync", 10 | "livereload", 11 | "serve" 12 | ], 13 | "main": "index.js", 14 | "dependencies": { 15 | "lodash": "^4" 16 | }, 17 | "devDependencies": { 18 | "husky": "^9", 19 | "lint-staged": "^15", 20 | "standard": "^17" 21 | }, 22 | "peerDependencies": { 23 | "browser-sync": "^2 || ^3", 24 | "webpack": "^1 || ^2 || ^3 || ^4 || ^5" 25 | }, 26 | "engines": { 27 | "node": ">=4" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "https://github.com/Va1/browser-sync-webpack-plugin.git" 32 | }, 33 | "homepage": "https://github.com/Va1/browser-sync-webpack-plugin", 34 | "author": "Valentyn Barmashyn ", 35 | "license": "MIT", 36 | "private": false, 37 | "lint-staged": { 38 | "lib/**/*.js": [ 39 | "standard --fix" 40 | ] 41 | }, 42 | "husky": { 43 | "hooks": { 44 | "pre-commit": "lint-staged" 45 | } 46 | } 47 | } 48 | --------------------------------------------------------------------------------