Varie comes with a bundler so you don't have to worry about configuration. It also comes with a fluent interface to help modify the webpack config, just in case you want to have more control over how your application is built.
There is is quite a bit that goes into a webpack bundler. You may need to customize some options, this is what is being used in our bundler :
- Babel
- SASS
- HTML
- cssnano
- TypeScript
- Browsersync
- autoprefixer
- Aggressive Code Splitting
- Hot Module Reloading (HMR)
- Case Sensitivity Path Checks
- Automation of cleaning of old builds
- Image optimizations for JPEG / PNG / GIF
- Vue
- Uses runtime only
- To use the runtime and compiler checkout Using Vue Runtime & Compiler.
- Custom Bundlers
- Bundle Analyzer
- Modern builds with legacy fallback
import { WebBundler } from "varie-bundler";
export default function(env) {
return new WebBundler(env)
.entry("app", ["app/app.ts", "resources/sass/app.scss"])
.aliases({
"@app": "app",
"@views": "views",aliases
"@store": "store",
"@config": "config",
"@routes": "routes",
"@models": "app/models",
"@resources": "resources",
"@components": "app/components",
})
.build();
};
To build your application you just need to run
$ npm run dev
or if you wish to build a modern build $ npm run dev-modern
We define some default path aliases for you already, but you can change these to however you like
.aliases({
"@app": "app",
"@views": "views",
"@store": "store",
"@config": "config",
"@routes": "routes",
"@models": "app/models",
"@resources": "resources",
"@components": "app/components",
})
[{.alert} The Varie-CLI does not know that these have been changed, and will not correctly put files in the correct locations!]
Adding a new entry consists of the name for the entry (the files output name), and an array of the entry.
.entry("admin", ["app/admin.ts", "resources/sass/admin.scss"])
Aggressive vendor splitting splits all of your vendors into individual bundles to leverage HTTP2. This should increase the loading performance of your application.
.aggressiveVendorSplitting()
To copy a directory / file you can multiple copy commands.
.copy('resources/assets/fonts') // outputs to fonts
.copy('resources/assets/fonts', 'resources/fonts') // outputs to resources/fonts
Sometimes you don't want to clean the dist folder entirely.
.dontClean('public/index.php')
You may need to setup some variables that are needed per environment within your application.
.varieConfig({
app : {
someKey : "someValue"
}
})
You then can access them with the $config
helper
$config.get("app.someKey");
To enable EsLint checking
.eslint()
You can add global styles to your Vue components.
.globalSassIncludes([
"resources/sass/variables/index"
])
If your application needs to parse through html files you can add the html loader
.html()
If you want to add some variables to your index.html such as a version number or envrioment variable
.htmlVariables({
VERSION : '1.0'
})
You can add custom Varie plugins by sending the entire plugin to the bundler.
.plugin(MyCustomPlugin)
An example plugin is Varie Tailwindcss Plugin
You may need to proxy your requests to your backend.
This example will proxy anything that is http://localhost/api*
to http://varie.test/api/*
:
.proxy("/api", "http://varie.test")
To purge unused CSS you can easily add the purge css plugin
.purgeCss(["app", "views", "node_modules/varie"])
If you have any web workers, you can enable the loader necessary for those to work correctly.
.webWorkers()
If you wish to use browserSync :
.browserSync()
The bundler is using webpack-chain, which allows a fluent interface to add / modify the webpack configuration file.
This allows you to modify the bundler without having to change the bundler itself.
You should get yourself familiar with the webpack-chain API as well as the source for varie-bundler
.chainWebpack((config, env) => {
config.when(!env.isProduction, () => {
config.plugin("webpack-notifier").tap(args => {
return [
/* new args to pass to webpack-notifier's constructor */
];
});
});
});
[{.info} Add in the inspect flag, $ npm run dev -- --inspect
, should help diagnos how to modify the webpack config with webpack-chain.]
.chainWebpack((config, env) => {
config.module
.rule('markdown')
.test(/\.md$/)
.use('html')
loader('html-loader')
.end()
.use('markdown')
.loader('markdown-loader')
.options({
//
})
.end()
});
.chainWebpack((config) => {
config.plugin('webpack-notifier')
.use(WebpackNotifierPlugin, [argument1, argument2])
.end()
});
You can analyze your bundle with webpack analyse
$ npm run analyze-dev
$ npm run analyze-prod
To inspect your configuration add the inspect
flag to your npm build command.
$ npm run inspect-dev
$ npm run inspect-prod
Varie provides ways to choose your browser capability with The .browerlistrc
and the babel.config.js
.
The BrowserList file allows to specify which browsers should be compatible with your build. These configurations
will be used by autoprefixer
and babel
.
Varie uses defaults
for its default which you can see on browserl.ist
This config allows you to pass all options into @babel/preset-env
, you can review those options (here)[https://babeljs.io/docs/en/babel-preset-env].
// babel.config.js
export default {
presets: [
[
"varie-app",
{
polyfills: ["es6.symbol"],
},
],
],
};
To remove unused CSS from your application, you can use the .purgeCss
method to scan all files for those classes.
.purgeCss([
'app',
'views',
'node_modules/varie'
], {
whiteListPatterns: [],
whitelistSelectors: [],
whitelistPatternsChildren: [],
})
To Learn more about white listing please visit the PurgeCSS webpack plugin's documentation https://github.com/FullHuman/purgecss-webpack-plugin.
To enable JSX pass jsx
in the babel options.
// babel.config.js
export default {
presets: [
[
"varie-app",
{
jsx: true,
},
],
],
};
BrowserList is a way to manage what browsers you support. There is a file called browserlistrc
which determines
what features should be compatible with.
The bundler supports a modern build configuration in which it will build two sets of assets. One that produces a legacy bundle for older browsers that do not support some of the newer features.
- Browsers that support the
type
ofmodule
will download the modern build. - Legacy browsers will not download the modern build and instead will use the legacy build automatically
- The Safari 10 fix is automatically injected into the template
$ npm run dev-modern
$ npm run prod-modern
[{.info} While the size may seem small, the code parsing and evaluation should improve overall performance of your app.]
To use the runtime and compiler you can pass in via the options parameter :
import { WebBundler } from "varie-bundler";
export default function(env) {
return new WebBundler(env, {
vue: {
runtimeOnly: false,
},
})
.entry("app", ["app/app.ts", "resources/sass/app.scss"])
.aliases({
"@app": "app",
"@views": "views",
"@store": "store",
"@config": "config",
"@routes": "routes",
"@models": "app/models",
"@resources": "resources",
"@components": "app/components",
})
.build();
}
If you need to build a UMD modules for you application use the UmdBundler
import { WebBundler, UmdBundler, multiCompiler } from "varie-bundler";
export default function(env) {
let configs = {};
configs["web"] = new WebBundler(env).entry("app", [
"app/app.ts",
"resources/sass/app.scss",
]);
configs["some-plugin"] = new UmdBundler(
env,
"PluginName",
"plugin/some-plugin.ts",
);
return multiCompiler(configs);
}
[{.alert} The multiCompiler
function is only required when using multiple bundlers!]
Since we are using typescript it is easy to create your own bundlers based on the Varie Bundler.
A good starting point is just to look at one of the bundlers we provide such as the WebBundler
:
export default class WebBundler extends AbstractBundler {
constructor(
mode: EnvironmentTypes = EnvironmentTypes.Development,
config: DeepPartial<BundlerConfig> = {},
) {
super(mode, config);
new loaders.Vue(this, this.config.vue);
new loaders.Sass(this, {
hashType: this.config.hashType,
});
new loaders.Fonts(this);
new loaders.Images(this);
new plugins.Html(this);
new plugins.Clean(this, this.config.plugins.clean);
}
}
[{.alert} Your custom bundler should include entries to allow webpack to parse the data!]