I've some global variables in ./src/assets/styles/_globals.scss. Now I want to add them to all Vue-Components so I'm able to use variables within the scoped styles.
I'm using Gridsome for which this works fine with the following configuration:
const path = require('path')
function addStyleResource (rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, './src/assets/styles/_globals.scss'),
],
})
}
module.exports = {
siteName: 'Gridsome',
plugins: [],
chainWebpack (config) {
// Load variables for all vue-files
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
// or if you use scss
types.forEach(type => {
addStyleResource(config.module.rule('scss').oneOf(type))
})
}
}
Furthermore I'm using StoryBook to get a web-view with all my components. This is my configuration:
module.exports = async ({config, mode}) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../src/assets/styles/'),
});
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader', {
loader: 'style-resources-loader',
options: {
patterns: [
path.resolve(__dirname, './src/assets/styles/_globals.scss'),
],
type: ['vue-modules', 'vue', 'normal-modules', 'normal']
}
}],
include: path.resolve(__dirname, './src/assets/styles/_globals.scss')
});
return config;
};
The configuration throws no error but used scss-variables within my scoped styles in my VueComponents could not be parsed/found.
How can I publish those global styles to all my components?
My folder structure is this:
*
- .storybook
-- webpack.config.js
- src
-- assets
--- styles
---- _globals.scss
-- components
--- // All my Vue-Components
Related
I have created some custom components on top of vuetify components. In order to match my design I have overridden the vuetify sass variables by creating a .scss file in path src/scss/variables.scss and written custom .scss as well. This works absolutely fine but when I try to import the components in my storybook I am unable to see the overridden design.
// .storybook/main.js
const path = require("path");
module.exports = {
stories: [
// "../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
addons: [
"#storybook/addon-links",
{
name: "#storybook/addon-essentials",
options: {
docs: true
}
}
],
webpackFinal: async (config, { configType }) => {
config.resolve.alias["~storybook"] = path.resolve(__dirname);
config.resolve.alias["#"] = path.resolve(__dirname, "..", "src");
config.module.rules.push({
test: /\.s(c|a)ss$/,
use: [
"style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
implementation: require("sass")
prependData: "#import '#/scss/variables.scss';", // ISSUE IS HERE
sassOptions: {
indentedSyntax: false // Tried with both true and false
},
}
}
],
include: path.resolve(__dirname, "../")
});
return config;
}
};
The existing configuration for compilation seems to have issues compiling some syntax used in sentry source code. The screenshot shows two places where the exception occurs.
Here is the configuration used
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const appDirectory = path.resolve(__dirname, '../')
// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
test: /\.js$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(appDirectory, 'index.web.js'),
path.resolve(appDirectory, 'src'),
path.resolve(appDirectory, 'prebundled'),
path.resolve(appDirectory, 'node_modules/react-native')
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// The 'metro-react-native-babel-preset' preset is recommended to match React Native's packager
presets: ['module:metro-react-native-babel-preset'],
// Re-write paths to import only the modules needed by the app
plugins: [
'react-native-web',
[
'module-resolver',
{
alias: {
'^react-native$': 'react-native-web'
}
}
]
]
}
}
}
// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
esModule: false
}
}
}
module.exports = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
path.resolve(appDirectory, 'index.web.js')
],
output: {
filename: '[name].[contenthash].js',
publicPath: '/',
path: path.resolve(appDirectory, 'dist')
},
module: {
rules: [
babelLoaderConfiguration,
imageLoaderConfiguration,
{
test: /\.tsx?$/,
loader: 'ts-loader',
// exclude: /node_modules/,
options: {
configFile: 'tsconfig.web.json',
transpileOnly: true
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.IgnorePlugin({
resourceRegExp: /react-native-screens/
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, './index.html')
}),
new CopyPlugin({
patterns: [
{
context: __dirname,
from: './images/**/*',
to: '[path][name][ext]',
force: true
},
{ from: path.join(__dirname, './main.css'), to: './main.css' },
{
from: path.join(__dirname, './.well-known/apple-app-site-association'),
to: './.well-known/'
}
]
}),
new webpack.HotModuleReplacementPlugin()
],
resolve: {
alias: {
'react-native$': 'react-native-web',
'react-native-maps$': 'react-native-web-maps'
},
extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js', '.json']
}
}
I tried implementing something that looks like showing in this documentation but it did not help.
https://docs.sentry.io/platforms/javascript/guides/react/sourcemaps/uploading/webpack/
You need to add #sentry/react-native to compile.
Update you webpack config like this:
...
const compileNodeModules = [
'#sentry/react-native'
]
const babelLoaderConfiguration = {
...
...compileNodeModules
}
In my vue.config.js file contains (ref: https://austingil.com/global-sass-vue-project/):
css: {
loaderOptions: {
sass: {
additionalData: `
#import "#/storybook-components/src/styles/utils/_variables.scss";
#import "#/storybook-components/src/styles/utils/_shadowMixins.scss";
`,
implementation: require('sass')
}
}
},
This allows me to use the sass variables within the vue components.
We have a central and shared storybook library for common components that was working perfectly, but now we share the variables it fails.
How can I share add the additionalData to the vue components in storybook? There is a vue.config file in the storybook project but I don't think it is being read...
The .storybook/main.js looks like (following the guides):
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = {
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
},
typescript: {
check: false,
checkOptions: {},
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
},
},
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
],
"framework": "#storybook/vue"
};
So I assume the additionalData is meant to be added to the webpack final section, I just cannot see how?
As usual.. the rubber duck affect kicked in after posting the question. This was a very annoying one to resolve.
The following config worked for me, note the expansion of the rule for the sass-loader.
Additional note: webpack was fixed in the dev deps to "webpack":"^4.46.0"
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = {
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
{
// Compiles Sass to CSS
loader: "sass-loader",
options: {
additionalData: `
#import "./src/styles/utils/_variables.scss";
#import "./src/styles/utils/_shadowMixins.scss";
`,
implementation: require('sass'),
},
},
],
include: path.resolve(__dirname, '../'),
});
// Return the altered config
return config;
},
typescript: {
check: false,
checkOptions: {},
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
},
},
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
],
"framework": "#storybook/vue"
};
I’m struggling a little with webpack, VUE and my CSS static files. See, I’d like to inject the styles that are in the Single File Components with the and I also want to have my static CSS file that has some useful classes. I’m running webpack 4 and I don’t clearly know how to approach the static CSS file situation.
This is my webpack config so far:
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMerge = require('webpack-merge');
const makeConfig = (mode) => require(`./build-utils/webpack.${mode}.js`)(mode)
const MiniCss = require('mini-css-extract-plugin');
module.exports = (env) => {
return WebpackMerge.merge(
{
mode: env.mode,
entry: './src/main.js',
output: {
filename: '[name].js',
publicPath: '/',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader'
},
{
test: /\.(js)$/,
exclude: /node_modules/,
use: [
{ loader: 'babel-loader' }
]
},
{
test: /\.(css)/,
use: [
MiniCss.loader,
'css-loader'
],
include: /\assets\.css$/
},
{
test: /\.(css)/,
use: [
'style-loader',
'css-loader'
],
exclude: /\assets\.css$/,
},
{
test: /\.(png|jpg|gif|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
esModule: false
}
}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new MiniCss()
]
},
makeConfig(env.mode)
)
}
I have my statics css under /src/assets. Then my CSS assets gets imported in the entry point javascript’s file. The problem is that I don’t get my static CSS file emitted. What’s the solution for both: have my static css and the Single Component CSS.
Thank you!
I use webpack.optimize.CommonsChunkPlugin to Generate an extra chunk(vueCommon.js) which contains vuejs、vue-router、vue-resource...;but I want to Generate another business commonChunk like util.js。they are used just in some pages by "import ajax from '../service/service.js'";
problems after build:
every generated page.js has the code of service.js。
brief demos:
https://github.com/wxungang/vueJs
//webpack.base.js
"use strict";
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const CONFIG = require('./config');
var projectRoot = CONFIG.projectRoot || path.resolve(__dirname, '../');
var _ENV = CONFIG.env || 'dev';//prod
module.exports = {
devtool: _ENV != 'prod' ? '#eval-source-map' : false,
context: __dirname,//http://wxungang.github.io/1104/vue
entry: {
app: path.join(projectRoot, './vue/app.js'),
page: path.join(projectRoot, './vue/page.js')
},
output: {
path: path.join(projectRoot, './build/vue-' + _ENV),
publicPath: '',//'./build/vue-'+_ENV+'/',//path.join(__dirname, '../src/build/dev/')
filename: '[name].js',
chunkFilename: 'chunks/[name].chunk.js',
// crossOriginLoading: 'anonymous'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js',
'vue-router$': 'vue-router/dist/vue-router.common.js'
},
modules: ["node_modules"],
mainFiles: ["index", "app"],
extensions: [".js", ".json", '.vue']
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this nessessary.
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
'less': 'vue-style-loader!css-loader!less-loader'
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader"
},
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.html$/,
loader: 'vue-html-loader'
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
plugins: [
//注入一些全局变量
new webpack.DefinePlugin({
_ENV_: _ENV,
_VERSION_: JSON.stringify("1.0.0")
}),
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
// (the commons chunk name)
filename: "vueCommons.js",
// (the filename of the commons chunk)
// minChunks: 2,
// (Modules must be shared between 3 entries)
// chunks: ["pageA", "pageB"],
// (Only use these entries)
// children: true,
// async: true,
}),
//可以和entry文件联合配置
new HtmlWebpackPlugin({
inject: false,
title: 'vueJs of app',
filename: 'app.html',
template: '../vue/entry/template.ejs',
scripts: ['./vueCommons.js', './app.js']
}),
new HtmlWebpackPlugin({
inject: false,
title: 'vueJs of page',
filename: 'page.html',
template: '../vue/entry/template.ejs',
scripts: ['./vueCommons.js', './page.js']
})
]
};
How did you use CommonsChunkPlugin to generate vueCommon.js?
A simple way is to add a new wepack entry like
utils: ['../service/service.js']
then add a new CommonsChunkPlugin instance in the webpack plugins array like this
new webpack.optimize.CommonsChunkPlugin('utils'),
the CommonsChunkPlugin will do the work by remove all utils module in other chunk files and generate only one utils.js.
Or you can just set minChunks option of the existing CommonsChunkPlugin into a number to wrap the vue file and utils together.