Zephraph
https://slides.com/zephraph/deck-7/live
Supercharging
Single file components
Justin Bennett
Front End Architect
Scripps Networks Interactive
Text
Let there be peace on CSS - Cristiano Rastelli, Badoo
Single File Component
<template>
<div class="greeting">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style scoped>
.greeting {
color: red;
}
</style>
Hello.vue
?
Loaders are transformations that are applied on the source code of a module.
Webpack
vue-loader
docs @ webpack.js.org
Helpful Hint #1
Use vue-cli or poi to save your sanity
<template>
<div class="greeting">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style scoped>
.greeting {
color: red;
}
</style>
Hello.vue
But what is it really?
<template>
<div class="greeting">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style scoped>
.greeting {
color: red;
}
</style>
// Template tag
module.exports = {
render: function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c('div', {
staticClass: "greeting"
}, [_vm._v(_vm._s(_vm.msg))])
}
}
// Script tag
__exports__["default"] = ({
data: function data() {
return {
msg: 'Hello world!'
};
}
});
// Styles tag
exports = __webpack_require__(9)();
exports
.push([
module.i,
".greeting[data-v-b5235a7e]"
+ "{ color: red; }"
]);
Helpful Hint #2
Use the ExtractTextPlugin to separate out css
What more can we do?
<template>
<button>Click Me</button>
</template>
<style scoped>
button {
background-color: red;
}
</style>
<style scoped>
button {
background-color: blue;
}
</style>
Helpful Hint #3
Single file components can have multiple style blocks
Multi-brand Theming
<template>
<button>Click Me</button>
</template>
<style scoped>
button {
width: 90px;
height: 30px;
font-size: 12px;
border-radius: 6px;
}
</style>
<style theme="hgtv" scoped>
button {
background-color: #0E9AB0;
color: white;
}
</style>
<style theme="diy" scoped>
button {
background-color: #9C1C4C;
color: white;
}
</style>
vue-loader doesn't care
How do I build this?
What does vue-loader do?
vue-template-compiler
(You probably shouldn't use this)
Run through parseComponent()
<template>
<button>Click Me</button>
</template>
<style scoped>
button {
width: 90px;
height: 30px;
font-size: 12px;
border-radius: 6px;
}
</style>
<style theme="hgtv" scoped>
button {
background-color: #0E9AB0;
color: white;
}
</style>
let output = compiler
.parseComponent(src);
console.log(output);
{
template: {
type: 'template',
content: '\n<button>Click Me</button>\n',
attrs: {},
...
},
script: null,
styles: [{
type: 'style',
content: '\nbutton {\n width: 90px;\n height: ...',
attrs: [Object],
scoped: true,
...
},
{
type: 'style',
content: '\nbutton {\n background-color: #0E9AB0...',
attrs: [{ theme: 'hgtv' }],
scoped: true,
...
},
{
type: 'style',
content: '\nbutton {\n background-color: #9C1C4C...',
attrs: [{ theme: 'diy' }],
scoped: true,
...
}
],
customBlocks: []
}
Multi-brand Theming
<style scoped>
button {
width: 90px;
height: 30px;
font-size: 12px;
border-radius: 6px;
}
</style>
<style theme="hgtv" scoped>
button {
background-color: #0E9AB0;
color: white;
}
</style>
<style theme="diy" scoped>
button {
background-color: #9C1C4C;
color: white;
}
</style>
Building for HGTV
Webpack
vue-loader
theme-loader
The anatomy of a loader
modules.export = function loader(source) {
return doSomethingWithSource(source);
}
webpack passes in module code
Return transformed source
vue-theme-loader
Graphql support
<template>
<div class="example">{{ Greetings.hello }}</div>
</template>
<graphql>
query Greetings {
hello
}
</graphql>
Webpack
vue-loader
graphql-loader
Text
Lack of editor support
Read the docs
Resources
Supercharging SFCs
By Justin Bennett
Supercharging SFCs
- 3,021