An open API service indexing awesome lists of open source software.

https://github.com/smartprix/sm-webpack-config

Webpack Configuration With Vue, Babel & Hot Reloading
https://github.com/smartprix/sm-webpack-config

webpack

Last synced: about 2 months ago
JSON representation

Webpack Configuration With Vue, Babel & Hot Reloading

Awesome Lists containing this project

README

        

# Webpack Configuration
Webpack configuration with following features:
* Hot Reloading in Development
* Production Optimized Build
* JSX and Vue
* Babel
* Eslint
* Sane Project Structure

# How To Use

## Install

Install this package
```bash
npm install sm-webpack-config --save-dev
```

**NOTE**: You need to install `node-sass` if you want to use sass, and `compression-webpack-plugin` if you want to use gzip option.

## Programmatic Usage
```js
const smWebpack = require('sm-webpack-config');

// Set Configuration [Optional]
const config = {
sourcePath: 'res',
destPath: 'static/dist',
publicUrl: '/static/dist',
sourceMap: true,
devServerPort: 3001,
appPort: 3000,
};

// Run Developement Server With Hot Reloading
smWebpack.runDevServer({config});

// Build For Production
smWebpack.runProdWebpack({config});

// If you want to go advanced and override some webpack configuration
const webpackConfig = {
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: true
}
}),
],
};

// Run Developement Server With Hot Reloading
smWebpack.runDevServer({config, webpackConfig});

// Build For Production
smWebpack.runProdWebpack({config, webpackConfig});

// NOTE: Both config & webpackConfig are optional
```

## CLI Usage

```bash
# Run devserver with default directory structure and ports assumed
sm-webpack serve

# Build for production with default
sm-webpack build
# OR
sm-webpack

# Build for development
sm-webpack build --dev

# Specifiy source and destination
sm-webpack build --src res/project1 --dest static/dist/project1

# Specify different ports
sm-webpack serve --dev-port 3050
```

### Using with config

Add a `sm-webpack.js` file to your project's root directory with the config for your project exported.
Or add a "sm-webpack" key to your package.json.

Eg. sm-webpack.js:
```js
module.exports = {
sourcePath: 'res/project1',
destPath: 'static/dist/project1',
publicUrl: '/static/dist/project1',
devServer: {
port: 3001,
appPort: 3000,
},
};
```

```bash
# Start project's dev server
sm-webpack serve

# Build project for production
sm-webpack
```

#### Multiple projects

If you have multiple projects you can export an object with multiple confs and use the `--config [keyName]` option to select project.

Eg. sm-webpack.js:
```js
module.exports = {
project1: {
sourcePath: 'res/project1',
destPath: 'static/dist/project1',
publicUrl: '/static/dist/project1',
devServer: {
port: 3001,
appPort: 3000,
},
},
project2: {
sourcePath: 'res/project2',
destPath: 'static/dist/project2',
publicUrl: '/static/dist/project2',
devServer: {
port: 3002,
appPort: 3000,
},
},
}
```

```bash
# Start project1's dev server
sm-webpack serve --config project1

# Build project2 for production
sm-webpack --config project2
```

## Using with Gulp
You can also use it in gulp using the following gulpfile
```js
const smWebpack = require('sm-webpack-config');
const gulp = require('gulp');

// The development server (the recommended option for development)
gulp.task('default', function(callback) {
smWebpack.runDevServer().then(callback);
});

// Build files for production
gulp.task('build', function(callback) {
smWebpack.runProdWebpack().then(callback);
});
```

Now you can use `gulp` to run dev-server and `gulp build` to build for production.

## Default Project Structure
* Keep all your client side code in `res`
* all javascript in `js`
* vue components in `components`
* 3rd party scripts in `vendor` (though they should generally be installed from npm)
* css / scss in `css`
* images in `img`
* other assests in `assests`
* eg. fonts can be kept in `assests/fonts`
* directly served static assests in `public`
* assests in this directory will not be compiled and copied directly to the `public` folder in dist
* this directory should be used as public root directory in your server config
* `index.html` as entry point (no need to include js/css, they will automatically be injected by webpack).

* all the compiled code will be put in `static/dist`
* point your static server to `static` directory
* use public path as `/static`
* api endpoints should start with `/api`
* Keep your server running at port `3000`
* Dev server will run at port `3001`

## Webpack Aliases
The following aliases are defined
```js
// by default config.sourcePath points to `res`, you can override it in your config
{
'@': config.sourcePath,
'res': config.sourcePath,
'js': path.join(config.sourcePath, 'js'),
'assets': path.join(config.sourcePath, 'assets'),
'components': path.join(config.sourcePath, 'js', 'components'),
'css': path.join(config.sourcePath, 'css'),
'img': path.join(config.sourcePath, 'img'),
}
```

So you can write `import Hello from 'components/Hello.vue'` from anywhere
If you want to use images in your vue templates use them as `~img/logo.png` (append a ~)
See https://github.com/vuejs/vue-loader/issues/193

## Configuration Options
```js
const config = {
// folder containing source files
sourcePath: 'res',

// where to put the compiled files
destPath: 'static/dist',

// at what url are these files accessible
// eg. if using a CDN, you can give http://static.smartprix.com/dist
publicUrl: '/static/dist',

// whether to generate source maps or not
sourceMap: true,

// whether to enable eslint or not
eslint: true,

// entry points for webpack (relative to sourcePath)
entry: {
app: 'js/index.js',
},

// html entry file, generated files will be auto-injected into this
entryHtml: 'index.html',

// whether the exported file should be a library
library: false,

// append hash of the file to the filename
appendHash: true,

// whether to minify the output or not
// false in developement, true in production
minify: false,

// whether to pre gzip the files
// makes a .gz file for each bundle produced
gzip: false,

// whether to delete the existing files in the destination folder
clean: true,

// whether to not display much info while running dev server
quiet: true,

// babel config
babel: {
// options for @babel/preset-env
// https://babeljs.io/docs/en/babel-preset-env.html
envOptions: {
// target these browsers
// default targets is based on browsers that support modules
targets: {chrome: '61', firefox: '60', safari: '11.1'},
},

// extra presets to include
includePresets: [],

// don't include these presets (if included by default)
excludePresets: [],

// extra plugins to include
includePlugins: [],

// don't include these plugins (if included by default)
excludePlugins: [],

// transform imports of the given modules to reduce code size
// see: https://www.npmjs.com/package/babel-plugin-transform-imports
transformImports: {},

// run babel in debug mode
debug: false,
},

// postcss config
postcss: {
// baseline for postcss-rem
remBaseline: 14,
// initial variables for postcss-simple-vars
variables: {},
},

// vue loader options
// see: https://vue-loader.vuejs.org/options.html
vue: {
compilerOptions: {
whitespace: 'condense',
},
},

// whether to generate analyzer report with the generated bundle
// false in development, true in production
// this can also be an object which will be passed to WebpackBundleAnalyzerPlugin
// analyzeBundle: {openAnalyzer: true, generateStatsFile: true}
analyzeBundle: false,

// whether to build a vue ssr bundle too
// default is false
// can be boolean true / false, or an object
// ssr: false,
ssr: {
// entry file of ssr bundle
entry: 'js/index-server.js',

// whether to generate source maps for ssr bundle
sourceMap: true,
},

// enable css modules support for all css files
// NOT: the following files already have module support regardless of this setting
// in .vue
// .module.css files
// .css?module files
cssModules: false,

// dev server and hot reloading options
devServer: {
// dev server middlewares
before(app, server) {},
after(app, server) {},

// dev server host
host: '0.0.0.0',

// dev server port
port: 3001,

// use https
https: false,

// whether to open the web browser
open: true,

// what port the app server is running
appPort: 3000,

// the paths to proxy on the dev-server
proxy: {
'/api': 'http://localhost:<appPort>',
'/static': 'http://localhost:<appPort>',
'/uploads': 'http://localhost:<appPort>',
},

// notify using os-native notification whenever an error occurs
notifyOnError: true,

// build the ssr bundle too when running dev server
// config.ssr must be set too
buildSSR: true,
},

// overrides for production environment
$env_production: {
minify: true,
eslint: false,
},

// overrides for development environment
$env_development: {
eslint: true,
},
};
```

## SSR (Server Side Rendering)
`sm-webpack-config` includes support for Vue SSR. Everything should work if you set the `config.ssr` option. Building will give bundles for both server side and client side.

Default bundle file names are as given by vue.
**Server Bundle:** `vue-ssr-server-bundle.json`
**Client Manifest**: `vue-ssr-client-manifest.json`

You'll need to use `createBundleRenderer` from `vue-server-renderer` for SSR. For more details see [Vue SSR docs](https://ssr.vuejs.org/guide/bundle-renderer.html#enter-bundlerenderer)

#### Running Dev Server With SSR
Running dev server with ssr support is a bit tricky. You'll need to use your own server and koa middleware provided by `sm-webpack-config` to set it up. `koaDevServer` fires a `vue-ssr` event with `{serverBundle, clientManifest}` as parameters whenever a new ssr bundle is ready.

Here's a quick example
```js
const Koa = require('koa');
const {createBundleRenderer} = require('vue-server-renderer');
const {koaDevServer} = require('sm-webpack-config');

const app = new Koa();

const template = fs.readFileSync('./res/index.html', 'utf-8');
function createRenderer(bundle, clientManifest) {
const options = {
clientManifest,
template,
runInNewContext: false,
};
return createBundleRenderer(bundle, options);
}

const buildConfig = {
// your build config
entry: {
app: 'js/index-client.js',
},
devServer: {
port: 3002,
appPort: 3000,
},
ssr: {
entry: 'js/index-server.js',
sourceMap: true,
},
};

const devServer = koaDevServer({
config: buildConfig,
});

let renderer;
// dev server fires vue ssr event whenever a new bundle is generated
// we replace the renderer each time it is fired (hot loading)
devServer.on('vue-ssr', ({serverBundle, clientManifest}) => {
renderer = createRenderer(serverBundle, clientManifest);
});
const renderToString = (...args) => {
if (!renderer) return 'Waiting to generate renderer...';
return renderer.renderToString(...args);
};

app.use(devServer.middleware());
app.use(async (ctx, next) => {
const ssrContext = {url: ctx.url};
ctx.body = await renderToString(ssrContext);
});

app.listen(3000);
```

**For a more complete setup with production + dev server ssr, see [SSR Example](examples/ssr)**

# Rollup
`sm-webpack-config` also includes rollup. You can use it as:
```js
const smWebpack = require('sm-webpack-config');

const config = {
entry: 'src/index.js',
dest: 'dest/index.js',
library: 'vutils',
libraryFormat: 'es',
minify: false,
sourceMap: false,

// overrides for production environment
$env_production: {
minify: true,
},

// overrides for development environment
$env_development: {
minify: false,
},
};

smWebpack.runRollup({config}).then(() => {
console.log("Done!");
});
```

#### Rollup Configuration Options
```js
const config = {
// entry point of the script (source)
entry: 'src/index.js',

// where to put compiled file
dest: 'dist/index.js',

// library name to give to the module
library: 'lib',

// what format should the compiled file be in
// this can be umd, amd, cjs (node like format), es (import / export), iife (for using in <script>)
libraryFormat: 'umd',

// whether to uglify the output
minify: false,

// whether to generate a sourcemap or not
sourceMap: false,
};
```