How to create a Node Packages to reuse Style Guide files in frontend? - rollup

In all my projects I make the same configuration, so not to waste time, I would like to create a Node Packages to reuse these configurations.
You can see the hierarchies of my folders:
Inside SRC it will be where the folder of each type of plugin that I will create and use will be, in this case we only have the "style-guide" at the moment.
Within the "style-guide" we have the following file hierarchies:
PS: As I use .husky to run commands in git hooks, I created a package inside this folder.
In the main hierarchy, you can see my configuration files:
ROLLUP.CONFIG.JS
import { babel } from "#rollup/plugin-babel";
import { terser } from "rollup-plugin-terser";
import external from "rollup-plugin-peer-deps-external";
import resolve from "#rollup/plugin-node-resolve";
import scss from "rollup-plugin-scss";
import typescript from "#rollup/plugin-typescript";
export default [
{
input: "./src/index.ts",
output: [
{
file: "dist/index.js",
format: "cjs",
},
{
file: "dist/index.es.js",
format: "es",
exports: "named",
},
],
plugins: [
scss({
output: true,
failOnError: true,
outputStyle: "compressed",
}),
babel({
exclude: "node_modules/**",
presets: ["#babel/preset-react"],
}),
external(),
resolve(),
typescript(),
terser(),
],
},
];
TSCONFIG.JSON
{
"compilerOptions": {
"target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"module": "esnext" /* Specify what module code is generated. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
"resolveJsonModule": true /* Enable importing .json files. */,
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
"strict": true /* Enable all strict type-checking options. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["src"],
"exclude": ["node_modules", "dist", "build", "coverage"]
}
PACKAGE.JSON
{
"name": "Frontend.NodePackages",
"license": "MIT",
"version": "1.0.0",
"main": "dist/index.js",
"module": "dist/index.es.js",
"files": [
"./dist"
],
"scripts": {
"build": "rollup -c"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"#testing-library/jest-dom": "^5.11.5",
"#testing-library/react": "^11.1.1",
"#testing-library/user-event": "^12.2.0",
"#types/jest": "^26.0.24",
"#types/node": "^14.14.6",
"#types/react": "^17.0.5",
"#types/react-dom": "^17.0.4",
"#types/react-router-dom": "^5.1.6",
"#types/styled-components": "^5.1.4",
"#typescript-eslint/eslint-plugin": "^4.6.1",
"#typescript-eslint/parser": "^4.6.1",
"babel-jest": "^27.1.1",
"babel-preset-react-app": "^10.0.0",
"eslint": "^7.2.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.0.0",
"jest": "^27.1.1",
"jest-cli": "^27.1.1",
"jest-watch-typeahead": "^0.6.1",
"jsdom": "^16.4.0",
"react-app-polyfill": "^2.0.0",
"typescript": "^4.4.2"
},
"devDependencies": {
"#babel/core": "^7.18.9",
"#babel/preset-react": "^7.18.6",
"#rollup/plugin-babel": "^5.3.1",
"#rollup/plugin-node-resolve": "^13.3.0",
"#rollup/plugin-typescript": "^8.3.3",
"#types/react": "^18.0.15",
"rollup": "^2.77.2",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-scss": "^3.0.0",
"rollup-plugin-terser": "^7.0.2",
"tslib": "^2.4.0"
}
}
In the root folder hierarchy (SRC), you can see the index.ts file where all folders and files inside src/* will be exported to the public:
export default "./style-guide/*";
Now the question:
How do I correctly export all these files and folder?
Can I reuse all these style-guide files, especially the .husky using
Node Packages?
Am I doing the configuration correctly?

Related

react-native-testing-library with typescript does not work

I've tried for days many ways to set up #testing-library/react-native with typescript following a sort of guides but still not able to render a simple component.
Roughly, my stack is react native with typescript and jest with ts-jest and react-native-testing-library. I'm following these guidelines among others:
Typescript React Native with Jest
Using TypeScript with React Native
Using with React Native
This is the error I'm getting for the simple test component below:
ReferenceError: React is not defined
Component:
import React from 'react'
import { View, Text } from 'react-native'
const SomeComponent = () => {
return (
<View>
<Text>Hello</Text>
</View>
)
}
export default SomeComponent
Test:
import { render } from '#testing-library/react-native'
import SomeComponent from './SomeComponent'
describe('<SomeComponent>', () => {
it('should render some component', () => {
const { getByText } = render(<SomeComponent />)
expect(getByText(/hello/i)).toBeDefined()
})
})
Follow a bunch of configurations for reference:
Dependencies:
{
"name": "connect",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "react-native start",
"debug": "open 'rndebugger://set-debugger-loc?host=localhost&port=8081' && react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
"pod": "npx pod-install",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"#airbrake/browser": "^2.1.7",
"#react-navigation/bottom-tabs": "^6.2.0",
"#react-navigation/native": "^6.0.8",
"#react-navigation/native-stack": "^6.5.1",
"#reduxjs/toolkit": "^1.8.0",
"#rneui/base": "^4.0.0-rc.1",
"#rneui/themed": "^4.0.0-rc.1",
"#types/react": "^17",
"#types/react-native-dotenv": "^0.2.0",
"#types/react-redux": "^7.1.23",
"axios": "^0.26.1",
"formik": "^2.2.9",
"http-status": "^1.5.0",
"moment": "^2.29.2",
"react": "17.0.2",
"react-native": "0.67.4",
"react-native-blob-util": "^0.13.8",
"react-native-dotenv": "^3.3.1",
"react-native-dropdownalert": "^4.5.1",
"react-native-error-boundary": "^1.1.12",
"react-native-loading-spinner-overlay": "^2.0.0",
"react-native-safe-area-context": "^4.2.2",
"react-native-screens": "^3.13.1",
"react-native-splash-screen": "^3.3.0",
"react-native-vector-icons": "^9.1.0",
"react-redux": "^7.2.6",
"redux-persist": "^6.0.0",
"redux-persist-filesystem-storage": "^4.0.0",
"use-debounce": "^7.0.1",
"yup": "^0.32.11"
},
"devDependencies": {
"#babel/core": "^7.12.9",
"#babel/preset-env": "^7.16.11",
"#babel/runtime": "^7.12.5",
"#react-native-community/eslint-config": "^3.0.1",
"#testing-library/jest-native": "^4.0.4",
"#testing-library/react-native": "^9.1.0",
"#types/jest": "^27.4.1",
"#types/react-native": "^0.66.15",
"#types/react-native-loading-spinner-overlay": "^0.5.3",
"#types/react-test-renderer": "^17.0.1",
"babel-jest": "^27.5.1",
"eslint": "7.32.0",
"jest": "^27.5.1",
"metro-react-native-babel-preset": "^0.70.1",
"react-addons-test-utils": "^15.6.2",
"react-native-typescript-transformer": "^1.2.13",
"react-test-renderer": "18.0.0",
"ts-jest": "^27.1.4",
"typescript": "^4.4.4"
},
"resolutions": {
"#types/react": "^17"
}
}
jest.config.js
const { defaults: tsjPreset } = require('ts-jest/presets')
module.exports = {
...tsjPreset,
preset: 'react-native',
transform: {
...tsjPreset.transform,
'\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
},
globals: {
'ts-jest': {
babelConfig: true,
},
},
transformIgnorePatterns: [
'/node_modules/(?!(#rneui|#react-native|react-native|react-native-size-matters|react-native-ratings|redux-persist-filesystem-storage|react-native-blob-util)/)',
],
setupFiles: ['./jest.setup.js'],
cacheDirectory: '.jest/cache',
}
babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module:react-native-dotenv',
{
moduleName: 'react-native-dotenv',
},
],
],
}
tsconfig.json
{
"compilerOptions": {
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": ["es2017"], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */
"jsx": "react-native", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"noEmit": true, /* Do not emit outputs. */
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
"strict": true, /* Enable all strict type-checking options. */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": false, /* Skip type checking of declaration files. */
"resolveJsonModule": true /* Allows importing modules with a ‘.json’ extension, which is a common practice in node projects. */
},
"exclude": [
"node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
]
}
tsconfig.spec.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"jsx": "react"
}
}
rn-cli.config.js
module.exports = {
getTransformModulePath() {
return require.resolve('react-native-typescript-transformer')
},
getSourceExts() {
return ['ts', 'tsx']
},
}
There is a similar open question about this setup here Setup for React Native/TypeScript/Testing Library/Jest not working
Thanks!
You need run npm install #babel/plugin-transform-react-jsx --save-dev into terminal and add plugin into babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module:react-native-dotenv',
{
moduleName: 'react-native-dotenv',
},
],
// add new plugin
[
'#babel/plugin-transform-react-jsx',
{
runtime: 'automatic',
},
],
],
}
You can use the official RNTL example that showcases a proper RNTL which also includes TypeScript.
Config issues like yours are hard to resolve as some small hard to notice issues might easily break the setup, so it's usually easiest to start with working setup.

Rollup bundling peer dependencies / Multiple instances of MUI make the ThemeProvider not work

I have two different repos I'm working on, lib and apps.
lib has some React components made with MUI that I want to consume in apps, and that's built with Rollup.
apps is a Lerna monorepo with a Next.js app that imports lib as a dependency to consume its components, which can be customized wrapping them in a <ThemeProvider> with a custom theme.
However, that doesn't work because there are duplicated instances of MUI / ThemeProvider, which I was able to verify by adding this to lib's entry point:
if (process.browser) {
(window as any)._React = React;
(window as any)._ThemeProvider = ThemeProvider;
}
And then this into apps':
if (process.browser) {
const {
_React,
_ThemeProvider,
} = window as any;
console.log(_React ? (_React === React ? "✅ Unique React" : "❌ Duplicate React") : "-");
console.log(_ThemeProvider ? (_ThemeProvider === ThemeProvider ? "✅ Unique ThemeProvider" : "❌ Duplicate ThemeProvider") : "-");
}
Which prints:
✅ Unique React
❌ Duplicate ThemeProvider
lib's component usage in app looks like this:
<ThemeProvider theme={ MY_CUSTOM_THEME }>
<MyComponent{ ...myComponentProps } />
</ThemeProvider>
Where both MyComponent and MY_CUSTOM_THEME are imported from lib, while ThemeProvider is imported from #mui/material/styles, just like it is in lib.
However, all MUI components will be displayed with the default theme.
Here are some of the relevant build files for both repos:
lib > package.json:
{
"name": "#myscope/lib",
"version": "1.0.0-alpha",
"description": "",
"main": "dist/cjs/src/index.js",
"module": "dist/esm/src/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"private": true,
"scripts": {
"build": "rollup -c",
},
"dependencies": {
"#apollo/client": "^3.4.5",
"#apollo/link-context": "^2.0.0-beta.3",
"#hookform/resolvers": "^2.8.5",
"#mui/icons-material": "^5.0.4",
"#swyg/corre": "^1.0.1",
"apollo-upload-client": "^16.0.0",
"atob": "^2.1.2",
"axios": "^0.24.0",
"btoa": "^1.2.1",
"country-codes-list": "^1.6.8",
"country-region-data": "^1.6.0",
"next": "^11.0.1",
"next-images": "^1.8.2",
"openpgp": "^5.0.0",
"react-hook-form": "^7.22.0",
"react-payment-inputs": "^1.1.8",
"react-use-country-region": "^1.0.0",
"styled-components": "^5.3.0",
"use-callback-ref": "^1.2.5",
"uuidv4": "^6.2.12",
"yup": "^0.32.11"
},
"peerDependencies": {
"#mui/material": "^5.0.4",
"react-dom": "^17.0.2",
"react": "^17.0.2"
},
"devDependencies": {
"#auth0/auth0-react": "^1.6.0",
"#babel/preset-react": "^7.16.7",
"#emotion/react": "^11.5.0",
"#emotion/styled": "^11.3.0",
"#graphql-codegen/cli": "^1.21.5",
"#graphql-codegen/introspection": "^1.18.2",
"#graphql-codegen/typescript-operations": "^1.18.0",
"#graphql-codegen/typescript-react-apollo": "^2.2.5",
"#graphql-codegen/typescript": "^1.22.1",
"#mui/material": "^5.2.8",
"#rollup/plugin-babel": "^5.3.0",
"#rollup/plugin-commonjs": "^21.0.1",
"#rollup/plugin-node-resolve": "^13.1.2",
"#rollup/plugin-typescript": "^8.3.0",
"#testing-library/dom": "^8.1.0",
"#testing-library/jest-dom": "^5.14.1",
"#testing-library/react": "^12.0.0",
"#testing-library/user-event": "^13.2.1",
"#types/jest": "^26.0.24",
"#types/react-dom": "^17.0.11",
"#types/react": "^17.0.16",
"#types/styled-components": "^5.1.12",
"#typescript-eslint/eslint-plugin": "^4.29.0",
"#typescript-eslint/parser": "^4.29.0",
"babel-jest": "^27.0.6",
"babel-plugin-styled-components": "^2.0.2",
"eslint-config-next": "^11.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-unused-imports": "^1.1.2",
"eslint": "^7.32.0",
"graphql": "^16.2.0",
"jest": "^27.0.6",
"prettier": "^2.3.2",
"rollup-plugin-dts": "^4.1.0",
"rollup-plugin-node-externals": "^3.1.2",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-typescript2": "^0.31.1",
"rollup": "^2.63.0",
"ts-jest": "^27.0.4",
"typescript": "^4.3.5"
}
}
Note that #mui/material appears both in peerDependencies and devDependencies, but not react or rect-dom, which are only listed as peerDependencies. That's because there's #types/react and #types/react-dom, but nothing similar for MUI, so the Rollup build would fail if it can't find the right types.
lib > rollup.config.js:
import commonjs from '#rollup/plugin-commonjs';
import dts from 'rollup-plugin-dts'
import resolve from "#rollup/plugin-node-resolve";
import typescript from 'rollup-plugin-typescript2'
import babel from '#rollup/plugin-babel'
import pkg from "./package.json";
// Extensions handled by babel:
const EXTENSIONS = [".ts", ".tsx"];
// Exclude dev and peer dependencies:
const EXTERNAL = [
...Object.keys(pkg.devDependencies),
...Object.keys(pkg.peerDependencies),
];
export default [{
input: 'src/index.ts',
output: [{
dir: "dist/esm",
sourcemap: true,
format: "esm",
preserveModules: true,
globals: {
react: "React",
},
}, {
dir: "dist/cjs",
sourcemap: true,
format: "cjs",
preserveModules: true,
globals: {
react: "React",
},
}],
external: EXTERNAL,
plugins: [
resolve(),
commonjs({
exclude: "node_modules",
ignoreGlobal: true,
}),
typescript({
useTsconfigDeclarationDir: true,
tsconfig: "rollup.tsconfig.json",
}),
],
}, {
input: './dist/types/src/index.d.ts',
output: [{ file: './dist/index.d.ts', format: "esm" }],
external: EXTERNAL,
plugins: [dts()],
}];
apps > lerna.json:
{
"packages": ["apps/**/*", "packages/**/*"],
"version": "0.0.1",
"npmClient": "yarn",
"useWorkspaces": true
}
apps > package.json:
...
"dependencies": {
"#myscope/lib": "file:../lib"
},
...
Note this is a file: import just to make it easier to develop and test changes.
I've also tried adding resolutions to both apps > package.json and apps > app > package.json, but no luck with that either...:
"resolutions": {
"#mui/material": "5.2.8"
}
It might not be the best solution, but I fixed this by exporting the ThemeProvider from lib:
export { ThemeProvider as MyComponentThemeProvider } from "#mui/material/styles";
Now, when using this one in app:
<MyComponentThemeProvider theme={ MY_CUSTOM_THEME }>
<MyComponent{ ...myComponentProps } />
</MyComponentThemeProvider>
Everything works as expected:
✅ Unique React
✅ Unique ThemeProvider
Also, take a look at https://github.com/facebook/react/issues/19541

How to configure eslint and prettier with nuxt 3?

I have installed these dependencies
Package.json:
{
"devDependencies": {
"#intlify/nuxt3": "^0.1.6",
"#nuxtjs/eslint-config": "^7.0.0",
"#nuxtjs/eslint-module": "^3.0.2",
"eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^3.0.0",
"eslint-plugin-vue": "^7.20.0",
"nuxt3": "latest",
"prettier": "2.4.1",
"sass": "^1.43.3",
"vite-plugin-eslint": "^1.3.0"
}
}
At .eslintrc.js
extends: [
'eslint:recommended',
'plugin:nuxt/recommended',
'prettier'
],
At nuxt.config.ts
import eslintPlugin from 'vite-plugin-eslint';
export default defineNuxtConfig({
...
vite: {
plugins: [eslintPlugin()]
},
buildModules: ['#intlify/nuxt3', '#nuxtjs/eslint-module',],
})
And none of these options are working with nuxt 3.
A simple ESLint + Prettier + TypeScript + Nuxt 3 (or Bridge) setup would look like this:
yarn add --dev eslint prettier eslint-config-prettier eslint-plugin-prettier #nuxtjs/eslint-config-typescript
.eslintrc.js
module.exports = {
root: true,
extends: ['#nuxtjs/eslint-config-typescript', 'plugin:prettier/recommended'],
}
package.json
{
"scripts": {
"lint": "eslint --ext .ts,.js,.vue ."
}
}
Here's a config i found here : https://github.com/nuxt/framework/discussions/2815#discussioncomment-2050408
// .eslintrc.json
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:#typescript-eslint/recommended",
"#nuxtjs/eslint-config-typescript"
],
"parserOptions": {
"ecmaVersion": "latest",
"parser": "#typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"vue",
"#typescript-eslint"
],
"rules": {}
}
If you really want to use prettier (imo eslint already does the job, using both can be very annoying to configure) you could add eslint-plugin-prettier library, then add "plugin:prettier/recommended" to eslint extends.
Idk what IDE you're using but if it's vscode, I advise you to use the linting on save instead of relying on formatters (Volar, prettier, eslint-prettier).
Mostly because it forces all devs to have the same format and rules

Sass-loader error 'options has an unknown property 'indentedSyntax'' when upgrading Vuetify from 1.5 to 2

I am upgrading Vuetify in my Vue CLI 3 project from version 1.5 to 2. I have followed these instructions, doing a full install. Since the upgrade, running 'npm run serve' gives me a ton of errors looking like this:
error in ./node_modules/vuetify/src/components/VGrid/_grid.sass
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
ValidationError: Invalid options object. Sass Loader has been initialised using an options object that does not match the API schema.
- options has an unknown property 'indentedSyntax'. These properties are valid:
object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }
at validate (C:\Users\kristoffer.dahl\Documents\Prosjekter\fridgein\fridgein_fe\node_modules\sass-loader\node_modules\schema-utils\dist\validate.js:50:11)
at Object.loader (C:\Users\kristoffer.dahl\Documents\Prosjekter\fridgein\fridgein_fe\node_modules\sass-loader\dist\index.js:36:28)
All errors look the same, except for the Vuetify component mentioned.
This is my package.json:
{
"name": "fridgein_fe",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"#fortawesome/fontawesome-svg-core": "^1.2.22",
"#fortawesome/free-brands-svg-icons": "^5.10.2",
"#fortawesome/free-regular-svg-icons": "^5.10.2",
"#fortawesome/free-solid-svg-icons": "^5.10.2",
"#fortawesome/vue-fontawesome": "^0.1.7",
"#vue/cli": "^3.11.0",
"#vue/cli-shared-utils": "^3.11.0",
"auth0-js": "^9.11.3",
"axios": "^0.18.1",
"dotenv": "^8.1.0",
"es6-promise": "^4.2.8",
"jquery": "^3.4.1",
"js-cookie": "^2.2.1",
"popper.js": "^1.14.7",
"register-service-worker": "^1.6.2",
"sockjs-client": "^1.3.0",
"vue": "^2.6.10",
"vue-float-action-button": "^0.4.4",
"vue-google-charts": "^0.3.2",
"vue-plugin-load-script": "^1.2.0",
"vue-router": "^3.0.2",
"vuetify": "^2.1.0",
"vuex": "^3.1.1",
"vuex-persistedstate": "^2.5.4",
"webstomp-client": "^1.2.6"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.4.0",
"#vue/cli-plugin-eslint": "^3.4.0",
"#vue/cli-plugin-pwa": "^3.11.0",
"#vue/cli-service": "^3.5.1",
"babel-eslint": "^10.0.1",
"babel-plugin-module-resolver": "^3.2.0",
"css-loader": "^2.1.1",
"deepmerge": "^4.0.0",
"eslint": "^5.0.0",
"eslint-plugin-vue": "^5.2.3",
"eslint-plugin-vuetify": "^1.0.0-beta.3",
"fibers": "^4.0.1",
"sass": "^1.23.0",
"sass-loader": "^8.0.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-vuetify": "^0.5.0",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.3.0",
"webpack": "^4.41.0"
},
This is my vue.config.js:
module.exports = {
css: {
loaderOptions: {
sass: {
data: `#import "~#/sass/main.scss"`
},
},
},
}
I have checked out and tried every solution presented in relevant issues on the developers' Github pages, but none has has any effect.
Has anyone else encountered this?
I had the same issue and fixed it by downgrading sass-loader by setting
"sass-loader": "7.3.1",
in package.json.
This was suggested on the Vuetify Discord
Actually you are using sass-loader 8+ and it has an option a little bit different.
Try using prependData instead of data.
Check this github issue
module.exports = {
css: {
loaderOptions: {
sass: {
prependData: `#import "~#/sass/main.scss"`
}
}
}
}
Update for those using version 10+. prependData is no longer valid. However you can use additionalData as a drop-in replacement.
Using the webpack 5.1.3 and sass-loader version 10.0.3, I had to use a different syntax (additionalData instead of prependData), as bellow:
webpack.config.js
{
test: /\.(css|scss|sass|less)$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
additionalData: '#import "assets/scss/_variables.scss";'
},
},
},
],
},
Bear in mind the syntax requires the double quotes in the path and the semicolon before the end of the single quote just as if you were writing a normal scss file.
Example:
'#import "path/_file.scss";'
In case you need to import multiple files you can use the template string symbol (``) as bellow:
{
test: /\.(css|scss|sass|less)$/,
use: [
...
{
...
options: {
sourceMap: true,
additionalData: `#import "assets/scss/_variables.scss";
#import "assets/scss/_mixins.scss";
#import "assets/scss/_misc.scss";`
},
},
},
],
},
You can also take the advantage of template string as bellow:
`#import "${path.resolve(APP_DIR, '/assets/scss/')}/_variables.scss";`
Be advised: I tried this approach to reduce bundle size and the result was terrible as when you start to see what the webpack is actually doing you return to the basic import all needed styles in your main component as sass-loader will actually prepend in multiple components the styles you inform in the additional data. In my case the bundle got 3 times it's original size.
Cheers
If you use NUXT you should configure like this:
//nuxt.config.js
loaders: {
less: {
lessOptions: {
javascriptEnabled: true,
modifyVars: {
'primary-color': '#5c6ac4',
'layout-body-background': '#fff'
}
}
}
}

Could not build project with vue cli 3 template due to svg in css

While moving to vue-cli 3 I encountered following problem.
I import a plugin's css to my app.scss.
This line: background-image: url(default-skin.svg); breaks yarn build, which throws this error:
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ReferenceError: navigator is not defined
Here is my vue.config.js:
const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin')
const ASSETS_DIR = 'static'
module.exports = {
assetsDir: ASSETS_DIR,
runtimeCompiler: true,
chainWebpack: config => {
config
.plugin('provide-plugin')
.use(webpack.ProvidePlugin, [{
axios: "axios",
$: "jquery",
jQuery: "jquery",
_: "lodash",
mapGetters: ['vuex', 'mapGetters'],
mapActions: ['vuex', 'mapActions']
}])
.end()
.plugin('copy-plugin')
.use(CopyWebpackPlugin, [
[{
from: path.resolve(__dirname, 'static'),
to: ASSETS_DIR,
ignore: ['.*']
}]
])
.end()
.plugin('sprite-loader-plugin')
.use(SpriteLoaderPlugin)
config.module
.rule('svg')
.test(/\.svg$/)
.use('file-loader')
.loader('svg-sprite-loader')
}
}
Any solution?
update
The css which breaks yarn build
Package.json:
{
"name": "f2c",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "Victor Ponamariov <victor.ponamariov#gmail.com>",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"animate.css": "^3.6.1",
"axios": "^0.18.0",
"blueimp-canvas-to-blob": "^3.14.0",
"fabric": "^2.3.3",
"flexboxgrid": "^6.3.1",
"intl-tel-input": "^12.4.0",
"jquery": "^3.3.1",
"libphonenumber-js": "^1.2.21",
"lodash": "^4.17.10",
"masonry-layout": "^4.2.1",
"moment": "^2.22.2",
"nprogress": "^0.2.0",
"perfect-scrollbar": "^1.4.0",
"photoswipe": "^4.1.2",
"portal-vue": "^1.3.0",
"raven-js": "^3.25.2",
"sharer.js": "^0.3.3",
"stickyfilljs": "^2.0.5",
"tippy.js": "^2.5.2",
"vee-validate": "^2.0.6",
"vue": "^2.5.2",
"vue-analytics": "^5.14.0",
"vue-carousel": "^0.9.0",
"vue-clipboard2": "^0.1.1",
"vue-cropperjs": "^2.2.0",
"vue-gtm": "^1.0.2",
"vue-i18n": "^8.0.0",
"vue-infinite-loading": "^2.3.3",
"vue-infinite-scroll": "^2.0.2",
"vue-meta": "^1.5.2",
"vue-mq": "^0.2.1",
"vue-multiselect": "^2.1.0",
"vue-perfect-scrollbar": "^0.1.0",
"vue-popperjs": "^1.2.6",
"vue-router": "^3.0.1",
"vue-select": "^2.4.0",
"vue-slider-component": "^2.7.4",
"vue-social-sharing": "^2.3.3",
"vue-star-rating": "^1.6.0",
"vue-sweetalert2": "^1.5.2",
"vue-tippy": "^2.0.18",
"vue-yandex-metrika": "^1.6.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^3.0.0-rc.5",
"#vue/cli-plugin-eslint": "^3.0.0-rc.5",
"#vue/cli-service": "^3.0.0-rc.5",
"copy-webpack-plugin": "^4.5.2",
"node-sass": "^4.9.2",
"normalize.css": "^8.0.0",
"postcss-import": "^11.1.0",
"postcss-url": "^7.3.2",
"sass-loader": "^7.0.3",
"svg-sprite-loader": "^3.8.0",
"vue-template-compiler": "^2.5.16",
"webpack-svgstore-plugin": "^4.0.3"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"globals": {
"$": false,
"jQuery": false,
"_": false,
"axios": false,
"VK": false,
"gapi": false,
"FB": false,
"mapGetters": false,
"mapActions": false
},
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-import": {},
"postcss-url": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
App folder structure:
I don't have a fix or full explanation, but there is a workaround...
The problem seems to be caused by postcss-import when importing the CSS file from inside a <style> tag of an SFC:
// App.vue
<style lang="scss">
#import 'app.scss'; /* imports default.css -> default-skin.svg */
</style>
You can workaround the build error by moving the import into the <script> tag (or to main.js):
// App.vue
<script>
import 'app.scss'; /* imports default.css -> default-skin.svg */
</script>
see GitHub repo
Try Deleting node modules folder and then run yarn install again.
If didn't work try:
global.navigator = {
userAgent: 'node.js'
};
Ref vue-pswipe, GuoQichen uses this config for svg.
config.module
.rule('svg')
.use('file-loader')
.clear()
.loader('url-loader')
.options({
limit: 4 * 1024,
name: 'img/[name].[hash:8].[ext]',
})