hjeti / vue-skeleton Goto Github PK
View Code? Open in Web Editor NEWA Vue skeleton
License: MIT License
A Vue skeleton
License: MIT License
We are already using hash filenaming for some assets. Which is great, because this optimizes caching: changed files get a different filename but assets that have not changed will still have the same path so they are cached by the browser. However, by putting assets in a /version/xxxx folder the path will change on every build, regardless of the contents of the asset has changed. This makes the hash in the filename redundant.
Currently, the longer a project gets, the longer a commit takes to complete linting, regardless of whether you are committing a large multi-file refactor or just a one-liner change.
Why ./src/assets/image and ./src/assets/font not copied in dist folder when we make build?
Currently we are loading locale files by putting jsons in the static folder and using a localeLoader function to load them from there. There is no reason these files can't be imported through webpack. This gives us all advantages of webpack bundling like using hash filenames for the locale files.
Generally speaking, we should not have any files in the static folder. The static folder should only be used for assets that are impossible or impractical to go through webpack.
In my current project, the jsons are placed in src/locale/
and the getTranslation
function in bootstrap.js
looks like so:
function getTranslation({code}) {
return import('./locale/' + code.toLowerCase() + '.json');
}
I noticed we also have a custom function that waits until the locales have loaded. Is there any reason not to use the Vue.initI18nManager
function provided by vue-i18n-manager
? See the note at the bottom of the getting started page.
key.pem located in /build-tools/ssl/ causes issues on repos such as http://agency-code.googlesource.com/.
Private keys should not be in the repo's history, to ensure a smooth sync between git remotes.
The fix requires tools like BFG:
bfg --delete-files key.pem
but can be quite dangerous if not used very carefully.
Currently the target in the tslint is set to ES6. And for instance when you do in Typescript:
[1,2,3].includes(value => value === 1)
It will throw an arrow that it can't find the method includes on an Array. There is more about this in this issue:
microsoft/TypeScript#2340
Setting it to ES7/es2017 fixes this. But I'm not sure if there are other implications or stuff that might be going wrong then?
If that is the case, we can leave it like this.
See the big notice on scss-lint repository.
in package.json
and in .stylelintrc
{
"extends": [
...
"stylelint-config-css-modules"
]
Currently there are two issues when using web workers related code in the Vue Skeleton:
"allowJs": true,
in the tsconfig.json
will make TS try to understand webworkers that are going through webpack and being changed, but TS will fail and say it's not a module (which it indeed isn't).window
reference in the webpack header of the worker file, which breaks in a web worker.Current workarounds:
// @ts-ignore
comment above the worker importsglobalObject: 'this',
to the output
section of the webpack config.For point 1 we cannot do much I think, people should just remember to do that.
For point 2 we could make an update to the skeleton to set it as a default.
shouldnt this fix always be there?
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV);
When pre-commit is enabled in package.json, if files are partially staged in git, all file changes are moved to staged instead.
Explanatory screen grab here (unlisted):
https://youtu.be/U2G7Sso9geU
The issue also stands when using the git CLI.
Should we add a name by default to the routes? This makes it simple to use the (localised) router-link.
Please update GSAP to version 2.0.2, because in SAFARI 11 doesn't work.
This is the issue:
https://github.com/greensock/GreenSock-JS/releases/tag/2.0.2
- FIXED: changed "const" to "var" in ES module files for better compatibility with older browsers (like IE and Safari).
Besis 💋
vue-skeleton/build-tools/script/build.js
Line 19 in e0161de
This line only throws when there is an actual JS error.
Below you can see errors that are webpack build errors (that don't throw), that are available in the stats
object.
To have this properly work, we need to check the stats
object for any errors, and throw an error after logging it.
�[1m�[31mERROR in ./node_modules/extract-text-webpack-plugin/dist/loader.js?{"omit":1,"remove":true}!./node_modules/vue-style-loader!./node_modules/css-loader?{"localIdentName":"[local]-[hash:base64:7]","importLoaders":true,"camelCase":true,"modules":true}!./node_modules/vue-loader/lib/style-compiler?{"vue":true,"id":"data-v-01964e59","scoped":false,"hasInlineConfig":true}!./node_modules/sass-loader/lib/loader.js?{"data":"@import /"src/asset/style/utils.scss/";","includePaths":["src/asset/style"]}!./src/App/App.scss
Module build failed: ModuleBuildError: Module build failed: Error: Missing binding source/frontend/node_modules/node-sass/vendor/linux-x64-57/binding.node
Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 8.x
Found bindings for the following environments:
- Linux 64-bit with Node.js 6.x
This usually happens because your environment has changed since running `npm install`.
Run `npm rebuild node-sass --force` to build the binding for your current environment.
at module.exports (source/frontend/node_modules/node-sass/lib/binding.js:15:13)
at Object. (source/frontend/node_modules/node-sass/lib/index.js:14:35)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Module.require (module.js:587:17)
at require (internal/module.js:11:18)
at Object. (source/frontend/node_modules/sass-loader/lib/loader.js:3:14)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Module.require (module.js:587:17)
at runLoaders (source/frontend/node_modules/webpack/lib/NormalModule.js:195:19)
at source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:364:11
at source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:170:18
at loadLoader (source/frontend/node_modules/loader-runner/lib/loadLoader.js:27:11)
at iteratePitchingLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
at iteratePitchingLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
at source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:173:18
at loadLoader (source/frontend/node_modules/loader-runner/lib/loadLoader.js:36:3)
at iteratePitchingLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
at iteratePitchingLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
at source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:173:18
at loadLoader (source/frontend/node_modules/loader-runner/lib/loadLoader.js:36:3)
at iteratePitchingLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
at runLoaders (source/frontend/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
at NormalModule.doBuild (source/frontend/node_modules/webpack/lib/NormalModule.js:182:3)
at NormalModule.build (source/frontend/node_modules/webpack/lib/NormalModule.js:275:15)
@ ./node_modules/extract-text-webpack-plugin/dist/loader.js?{"omit":1,"remove":true}!./node_modules/vue-style-loader!./node_modules/css-loader?{"localIdentName":"[local]-[hash:base64:7]","importLoaders":true,"camelCase":true,"modules":true}!./node_modules/vue-loader/lib/style-compiler?{"vue":true,"id":"data-v-01964e59","scoped":false,"hasInlineConfig":true}!./node_modules/sass-loader/lib/loader.js?{"data":"@import /"src/asset/style/utils.scss/";","includePaths":["src/asset/style"]}!./src/App/App.scss
@ ./src/App/App.vue
@ ./src/App/index.js
@ ./src/bootstrap.js�[39m�[22m
You can preview your build by running: yarn preview
You can analyze your build by running: yarn analyze
Webpack Bundle Analyzer saved stats file to source/frontend/stats.json
source/frontend> cp -pr dist/* $DEPLOY_PATH/web/
Exit code: 0 (141475ms)
I think the latest change in the mutations/actions/getter constants has been very good (getting rid of the namespace), but i still think it can be improved upon. I have three suggestions, which is basically the system i have been using for quite a while and which not everyone seems to like, but i think we should at least implement the first one.
1. combine them into an object per store
Each constant is now exported separately, which seems a bit weird since we don't do that anywhere else (it would be like exporting each RouteName entry separately). But more practically, if i have a bunch of stores with each a bunch of mutations (SET_USERNAME, SET_SCORE), whenever i want to auto-fill/import something by typing "SET_", i get a very big list of entries to choose from, and it will be not clear to what store they belong and what they do (since the constant typically doesn't contain the store name).
I think exporting those constants like this would be more practical:
export const appStore = {
SET_DEVICE_STATE: `${namespace}/setDeviceState`,
}
In my opinion this is a lot easier to use. You just type that storename somewhere, autoimport it and the autocomplete lets you explore whatever values it has on it.
2. categorize constants per store
I would go even further and group those values, since it's not always clear what a specific constant is (especially mutations and actions, their names can sometimes be a bit similar - although i think these two will be merged by vuex somewhere in the future).
export const appStore = {
mutation: {
SET_DEVICE_STATE: `${namespace}/setDeviceState`,
},
action: {
LOGIN: `${namespace}/login`,
}
}
I think using this in a component will make it very readable as well:
...mapActions({
login: userStore.action.LOGIN,
});
3. automatically fill those values
Regardless of whether we add the 2nd suggestion, i personally don't see why you wouldn't want to automatically set all those values instead of duplicating things, although this approach wasn't universally liked :)
export const appStore = initStoreConstants({
mutation: {
SET_DEVICE_STATE: null,
SET_USERNAME: null,
},
}, namespace);
(instead of the null values, this could also be done by what seng-event does with EVENT_TYPE_PLACEHOLDER)
Let me know what you think. Like i said, i think we should at least implement the first one to avoid the big list of options whenever you start typing SET_
i have had a few projects were i was not able to run the devserver (with https set to true) on ios. iirc, the page seemed to be constantly refreshing itself
In some cases, the dev server console will simply say "Failed to compile with errors" without actually listing the errors. This is not very helpful. I suspect it is due to FriendlyErrorsWebpackPlugin
. If I remove it and disable the quiet
option in the devServer
config, the errors show up again.
Hi HJ! ✨✨
I'm using global CSS classes to reuse styles in elements for example,
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
The problem arises when I want to step on some of the rules since in dev the compilation order of the css is different than in production
Is there a way for the compilation order to be the same in dev as prod?
Besis! ❤️ 💋 💋 💋
Currently when using one of the following Lodash functions: get, has or set in your project they break when running a production build. This is due to the webpack LodashModuleReplacementPlugin, which has a flag for allowing those methods, https://github.com/lodash/lodash-webpack-plugin.
Adding this to thewebpack.prod.conf.js
file should allow you to use those methods in your project!
new LodashModuleReplacementPlugin({
paths: true,
}),
The name Pages is not really descriptive...if i had to guess, it would be what PageNames is now: just some names to refer to a page, regardless of any context.
Instead, Pages holds values that are used in a very specific way: they are the paths to the pages. My suggestion would be to rename it to PagePaths
Something you want to use a mediaQuery with more than 1 condition like:
"(min-width: 768px) and (orientation: landscape)"
The SCSS importer doesn't understand this so you have to add extra quotes around it:
"'(min-width: 768px) and (orientation: landscape)'"
Unfortunately the DeviceStateTracker doesn't understand this anymore, so we could add a replace regex in the DeviceStateTracker, or parse the JSON with the replace in the startUp.
So something like:
`const cleanQueries = {};
Object.keys(mediaQueries).forEach(key => {
cleanQueries[key] = mediaQueries[key].replace(/'/g, '');
});
new DeviceStateTracker({
mediaQueries: cleanQueries,
deviceState,
showStateIndicator: process.env.NODE_ENV !== 'production',
})`
Node 10 came out about a week ago.
Attempting to use Node10 in the vue-skeleton triggers an error with the upath
node module: the version used by this project is not configured correctly to recognize Node10 as a valid version, and thus fails any attempt to, for example, build & run the local dev server.
Running yarn upgrade
after having upgraded to Node10 fixes this (obviously), but also outputs a warning about gulp-util
, with this Medium post linked.
Should this be taken care of in this project, or be left up to whoever builds their own project off of this one?
Most of the time the search query parameters are used for tracking stuff (GTM). But upon navigating without a Vue app those parameters are removed.
This causes issues with the tracking instances and we might not want that.
There is a solution with a beforeEach hook:
https://stackoverflow.com/questions/42226479/how-to-hold-url-query-params-in-vue-with-vue-router
We could/should look into this as well. Since it's very important for our customers to have the query parameters for tracking instances.
In Gaia this was hacked in later as well, because we needed it.
We could create a default set of parameters to send through, or work with options in the url. Since the default Vue app wouldn't use those query parameters.
I think the current implementation of a store is over complicated and inconsistent. Specially the way we use the index.js file with the constants.
Or we should go all the way with constants and use them everywhere. Or we are not using them at all.
If we go all the way, then we should use constants not only for mutations (btw I think we should name them "{{name_pc}}Mutations" instead of "{{name_pc}}MutationTypes", they are not "type" of mutations, they are all normal mutations) but for everything. So also for the values, the getters and so on. But this will lead to very unclear code. Even within a simple example:
export const Values = {
FIRST_NAME: 'firstName',
LAST_NAME: 'lastName',
};
export const Getters = {
FULL_NAME: 'fullName',
};
export default {
namespaced: true,
state: {
[Values.FIRST_NAME]: 'John',
[Values.LAST_NAME]: 'Do',
},
getters: {
[Getters.FULL_NAME]: ({ [Values.FIRST_NAME]: firstName, [Values.LAST_NAME]: lastName }) =>
`${firstName} ${lastName}`,
},
};
Compared that to:
export default {
namespaced: true,
state: {
firstName: 'John',
lastName: 'Do',
},
getters: {
fullName: ({ firstName, lastName }) => `${firstName} ${lastName}`,
},
};
Although I am normally a huge fan of using constants, I think for this case it will only add unnecessary clutters and complexity. And this is not (In my opinion) what Vue is designed for. So I would suggest to remove all the constants in the store.
Currently both original and optimized SVGs are part of the files being committed. Can't the optimized SVGs be ignored? This way the repo of your project stays clean from rendered/compiled files.
If the vue-skeleton
is used in a subdirectory inside a git repository this error will show up when trying to commit.
husky > npm run -s precommit (node v7.0.0)
fatal: Not a git repository: '.git'
husky > pre-commit hook failed (add --no-verify to bypass)
as /config/index.js
example tried with:
"dev": "cross-env NODE_ENV=development node build/dev-server.js -- --publicPath=/v/vue-skeleton/
and
"dev": "cross-env NODE_ENV=development node build/dev-server.js --publicPath=/v/vue-skeleton/
but configManager.getVariable(VariableNames.PUBLIC_PATH)
was always /
If I understand correctly, we want our namespaced store modules to provide the following:
I found the following structure to be useful to achieve this:
// the namespace itself
export const EntitiesNamespace = 'entities';
// action names
export const GET_COLLECTION = 'getCollection';
export const AUTOFETCH_COLLECTION_REFS = 'autoFetchCollectionRefs';
export const GET_ENTITY = 'getEntity';
// each action name prefixed with the namespace
export const EntitiesActions = { GET_COLLECTION, GET_ENTITY, AUTOFETCH_COLLECTION_REFS };
// mutation names
export const SET_COLLECTION_DATA = 'setCollectionData';
export const SET_ENTITY = 'setEntity';
// each mutation name prefixed with the namespace
export const EntitiesMutations = { SET_ENTITY, SET_COLLECTION_DATA };
// getter names
export const COLLECTION_ENTITIES = 'collectionEntities';
export const COLLECTION_FULL_ENTITIES = 'collectionFullEntities';
export const COLLECTION_TOTAL = 'collectionTotal';
// each getter name prefixed with the namespace
export const EntitiesGetters = {
COLLECTION_ENTITIES,
COLLECTION_TOTAL,
COLLECTION_FULL_ENTITIES,
};
// this function will do the actual prefixing
prefixNamespace(EntitiesNamespace, EntitiesActions, EntitiesMutations, EntitiesGetters);
export default {
namespaced: true,
...
};
It is technically possible to automatically build the objects for the prefixed constants based on the exports. The reason I create them statically first and then patch them afterwards with prefixNamespace
is so our IDE can statically analyse the objects and understand the properties in them.
What do you think about this approach? Once I have some time, I can submit a PR for this. If someone else wants to pick this up, feel free.
yarn eslint
throws an error because of a wrong configuration file, we should update the eslint dependency to 4.9.0, see this issue airbnb/javascript#1599
There are a couple of resets/base CSS functionality that I'm copying in each new project that I think should/could be easily included in the project.
I've create a branch "feature/base-scss" where I've added a simple reset (box-sizing, headings, paragraphs, lists).
Besides that I included folders for project specific "functions" and "mixins". Where we can place those that are specific for each project.
With this branch I'm just providing my opinion on how this could be. So please include you're suggestions.
The reason for this is that I think it would be good if there is a similar approach on base styling within each project.
The base can also include global copy styling. Which I think is really helpfull.
TSLint is updated and now has properly implemented the exclude functionality. We should update and enable linting again using the latest version.
In my opinion it is very confusing that we have the RouteNames.js and the RoutePaths.js. In practice I see a lot of developers using the RouteNames in one file and RoutePaths in an other, which leads to unclear code.
I think we should always use the route name for navigation and only the path for the declaration. Therefor there is no need to have a separate RoutePaths file. So the RoutePaths file should be removed.
We've implemented push pre-hooks that lints your files before pushing. It's kind of annoying when throwing errors when just fiddling with code. I think it feels a bit counterproductive. I'm suggesting to turn it off while runnning the dev server. And let the linting be done by the IDE.
We have the BundleAnalyzerPlugin
enabled by default on prod builds. However, this may cause the build to consume a lot of memory or even crash (I just encountered this with a dev who was running Node v9). This is likely because it generates a stats file (generateStatsFile: true
) which is a huge json file. This causes large memory consumption when node is trying to stringify the json.
What we can do is configure the stats file not to include irrelevant information. Some options (like source
) make the stats object very big. However, I think it's worth considering removing the bundle anlyzer from the prod builds. Most of the time we run a build, we don't check the analyzer output. Instead, when running the yarn analyze
command we execute a build just for that purpose. It will make the analyze command significantly slower, but I think we use it less often than we do production builds.
All imports are written in a absolute way. Should be relative.
Why?
Example
src/config/localeConfig.js
import { PropertyNames, VariableNames } from 'data/enum/configNames';
import { getValue } from 'util/injector';
import { CONFIG_MANAGER } from 'data/Injectables';
const getLocaleConfig = () => {
const configManager = getValue(CONFIG_MANAGER);
const languages = configManager.getProperty(PropertyNames.AVAILABLE_LOCALES).map(locale => {
if (typeof locale === 'string') {
return {
code: locale,
urlPrefix: locale,
translationKey: locale,
};
}
return locale;
});
const config = {
persistent: false,
defaultCode: configManager.getProperty(PropertyNames.DEFAULT_LOCALE),
languages,
};
return {
localeEnabled: configManager.getVariable(VariableNames.LOCALE_ENABLED),
localeRoutingEnabled: configManager.getVariable(VariableNames.LOCALE_ROUTING_ENABLED),
config,
};
};
export default getLocaleConfig;
The default loader for .svg is an svg-inline-loader
. What is the reasoning behind this? This will inline the svg as an svg tag (so <svg .... </svg>
)
The result of this is when you use an svg in your styling:
background-image: url('some-svg.svg');
The result will be an svg tag inside your css:
background-image: url('<svg .... </svg>');
Which is not valid syntax. If you do want to use the inline loader, I think it's a better to explicitly opt-in to it in your import:
import svgTag from '!!svg-inline-loader!./some-svg.svg';
Hi DJ HJ! 🎵
Your starter is amazing, but I had some issues.
When using the multi-language site and want to access the Vuex of the translations, for example, this.$store.getters.translation.home.title, Vue does not yet recognize any translation property and throw undefined error. This happens only if we load the site for the first time on the page that requires that store. The weird is that if I enter the site with the second language it works correctly.
variables: {
[VariableNames.LOCALE_ENABLED]: true,
[VariableNames.LOCALE_ROUTING_ENABLED]: true,
}
properties: {
[PropertyNames.DEFAULT_LOCALE]: 'en-gb',
[PropertyNames.AVAILABLE_LOCALES]: ['en-gb','es-es'],
}
{ "home":{ "title":"page home" } }
{ "home":{ "title":"página home" } }
export default {
name: 'HomePage',
mounted(){
console.log(this.$store.getters.translation.home.title);
}
};
If the error is mine do not hesitate to tell me. And thanks for sharing this starter. 💋 💋
Because vue is quite flexible, I think we can benefit from using linting rules specifically aimed at vue. Vuejs maintains their own eslint plugin:
https://github.com/vuejs/eslint-plugin-vue
I haven't looked into which rules/presets we should be using for this plugin. Any suggestions?
With the GSAP library installed from NPM, we don't get the extra Business plugins.
By default it's not possible to load them, because they all require 'TweenLite' from the folder where you put it.
For a current project I'm putting the extra plugins in the vendor/gsap folder. And adding a resolve alias for Webpack. This makes it possible to load the external plugins.
I suggest we can always add this in the skeleton, since it shouldn't break anything anyway.
In the webpack.base I've added this to the resolve alias object:
'TweenLite': path.resolve(projectRoot, 'node_modules/gsap/src/uncompressed/TweenLite'),
Hi team!
Is it possible to add a variable to change the host easier? Since when I have to try a mobile site I have to change 'localhost' to my IP in many files
Besis! 💋
The skeleton currently has typescript support, but all of the modules are plain JS by default. Some modules might be impractical to write in TS (like the components), but is there any reason not to do easy ones in TS? For example, the utils. Even if your project does not use typescript, you still get the benefit from IDEs like Webstorm better understanding the typings of the skeleton code.
Can the favicon generator be added?
I added it manually and it worked fine.
"favicons-webpack-plugin": "^0.0.7"
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
new FaviconsWebpackPlugin({
logo:path.resolve(__dirname, '../static/image/favicon.png'),
prefix: config.build.versionPath + "static/favicons/icon-[hash]",
emitStats: false,
statsFilename: 'iconstats-[hash].json',
persistentCache: false,
inject: true,
background: '#fff',
title: '',
icons: {
android: true,
appleIcon: true,
appleStartup: false,
coast: false,
favicons: true,
firefox: true,
opengraph: true,
twitter: true,
yandex: true,
windows: true
}
})
😘 😘 😘 😘 😘
Currently we have a component/index.js
module where you can globally register components. Even though this provide somewhat of a convenience, I think it's better to explicitly import components when we want to use them. This makes it clearer where the components come from.
Furthermore, this construction has caused circular dependency problems for me. When a component is imported this way and uses some constants from a vuex store module, these exports may be undefined at the moment the component module is parsed.
I really like this scaffolding solution that you are building here. Seems quite well thought and build for big applications.
Would be very useful to have the option to do SSR first.
Is this something in your roadmap?
Thank you
When using vue-skeleton, everyone has the freedom to change the tsconfig.json
compiler options to best serve their project. However, I think it would be good to have a more strict set of options by default. This will improve stability of our code. My suggestion is to add strict: true
. This will set all of the following to true
:
In my experience, I think noImplicitAny
and strictNullChecks
have the largest advantage in terms of preventing errors at runtime. You can read an explanation here and here
In "seng-scss" we have a "hover" mixin. But unfortunately this isn't working the way it's supposed to work from within the node-module.
The idea is to use a global class (most of the time a touch check from modernizr) as a prefix to the element. And then add :hover to the rule before displaying all content.
I think this is a nice solution to easily maintain hover states for supported devices only.
The problem with this is that we're working with CSS modules, where the local classes will interfere with the global classes. And also, by default, the modernizr isn't set-up to add the notouch class.
For the last couple of projects @larsvanbraam and myself used an adaptation from the hover mixin within our projects where we put the mixin in the global scope, and add the local selector to the mixin.
We've put this in asset/style/util/mixin/ and I think this would be a good idea to keep it by default there.
This will make sure the target is targeted correctly and we are easily able to update the check for when you want to support this custom hover functionality.
The mixin is as following:
@mixin scoped-hover($selector: null, $extraSelector: null) {
// Add the no-touchevents to the global scope and locally use the provided selector
:global .no-touchevents {
:local {
#{$selector}:hover {
@content;
}
}
}
// When we have an extra selector like 'is-hover' we want to use that in the global selector
@if $extraSelector {
:global .no-touchevents #{$extraSelector} {
:local {
#{$selector} {
@content;
}
}
}
}
}
Usage of this would be to put outside of the :local scope the following code:
@include scoped-hover('.link') {
color: red;
}
We could remove the .no-touchevent, because the Modernizr set-up is empty by default. Or keep it as an option somehow.
Very curious on more ideas about this, and what you think.
componentImage() is camel cased so style linter breaks. Should be component-image()
Expected "componentImage" to be "componentimage" function-name-case
Maybe stop using vue-types?
related: vuejs/eslint-plugin-vue#389
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.