configureWebpack function mode How to configure unplugin-vue-components plugin? - vue.js

```
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
configureWebpack: {
plugins: [
Components({
resolvers: [ElementPlusResolver()]
})
]
},
============================================================================
How to change the above plugin to the following way?
configureWebpack: (config) => {
//How to do it here
}

Related

How use vue-i18n with vue2, vite?

i'm migrating from webpack to vite, but there is a problem that I can't find a plugin to use i18n
I tried to use #intlify/vite-plugin-vue-i18n: 6.0.1, it doesn't seem to be work
now my package version:
vue: 2.6.11
vue-i18n: 8.17.0
#kazupon/vue-i18n-loader: 0.5.0
#intlify/vite-plugin-vue-i18n: 6.0.1
vite: 2.9.15
vite-plugin-vue2: 2.0.2
vite.config.js
/* cSpell:disable */
import { defineConfig } from 'vite';
const { resolve } = require('path');
import { createVuePlugin } from 'vite-plugin-vue2';
import copy from 'rollup-plugin-copy';
import { viteCommonjs } from '#originjs/vite-plugin-commonjs';
import clear from 'rollup-plugin-clear';
import vueI18n from '#intlify/vite-plugin-vue-i18n';
import { createI18nPlugin } from '#yfwz100/vite-plugin-vue2-i18n';
const destDir = `../var/dist/views`;
const host = 'localhost';
let filePort;
try {
const port = require('../port');
filePort = port && port.front;
// eslint-disable-next-line no-empty
} catch (error) {}
const listenPort = filePort || '10210';
const pages = {
cn: {
dir: 'pages',
template: 'cn.html',
entry: 'cn.js'
},
'vue-test': {
dir: 'vue-test/index',
template: 'index.html',
entry: 'index.js'
}
};
const multiplePagePath = 'src/pages';
const copyFileList = [];
Object.values(pages).forEach(item => {
copyFileList.push({
src: `${multiplePagePath}/${item.dir}/${item.template}`,
dest: destDir + '/' + item.dir,
transform: (contents, filename) =>
contents
.toString()
.replace(
'<!-- viteDevelopmentCopyReplaceHref -->',
`<script src="//${host}:${listenPort}/${multiplePagePath}/${item.dir}/${item.entry}" type="module" ></script>`
)
});
});
export default defineConfig({
resolve: {
alias: { src: resolve(__dirname, './src') },
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
server: {
port: listenPort,
// https: true,
hmr: { host },
origin: `//${host}:${listenPort}`
},
plugins: [
createVuePlugin(),
clear({
targets: ['../var']
}),
copy({
targets: [...copyFileList, { src: 'src/pages/*.html', dest: destDir }, { src: 'src/pages/layout', dest: destDir }],
verbose: true,
hook: 'buildStart'
}),
vueI18n({
// if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
// compositionOnly: false,
// you need to set i18n resource including paths !
// include: resolve(__dirname, './path/to/src/locales/**'),
compositionOnly: false
})
]
});
index.vue
<i18n>
{
"en-us": {
"language": "Language",
"hello": "hello, world!"
},
"zh-cn": {
"language": "言語",
"hello": "こんにちは、世界!"
}
}
</i18n>
<template>
<div id="app">
<p>{{$t('language')}}</p>
</div>
</template>
<script>
</script>
when i open the page, the text has not been translated and there is a warning in console:
[vue-i18n] Cannot translate the value of keypath 'language'. Use the value of keypath as default
Can anyone help me on this? Thanks in Advance
#intlify/vite-plugin-vue-i18n does not support custom block in Vue 2.
You should use unplugin-vue-i18n with vue-i18n-bridge.
Minimal examples of Vue2 + VueI18n custom block + Vite:
Vue<=2.6: https://stackblitz.com/edit/vitejs-vite-wk6hhj
Vue 2.7: https://stackblitz.com/edit/vitejs-vite-elfdtq
I18n Legacy API:
Vue<=2.6: https://stackblitz.com/edit/vitejs-vite-ed3cmt

Metro config not accepting blockList

I am building a react-native app with expo, I am using the modules of react-native-svg-transformer and also amplify (where I have created functions). The problem is that the functions in the amplify directory have package.json files and do not work. This is why I'm trying to put the amplify directory in the blocList of the metro configuration, but I keep getting the error:
Failed to construct transformer: TypeError: Transformer is not a constructor
This is my metro config:
const { getDefaultConfig } = require("expo/metro-config")
// extra config is needed to enable `react-native-svg-transformer`
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig(__dirname)
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer"),
assetPlugins: ["expo-asset/tools/hashAssetFiles"],
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"],
blockList: [/amplify.*/]
},
}
})()
I also tried this but it didn't work either:
const { getDefaultConfig } = require("expo/metro-config")
// extra config is needed to enable `react-native-svg-transformer`
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig(__dirname)
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer"),
experimentalImportSupport: false,
inlineRequires: true,
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"],
blockList: [/amplify.*/]
},
}
})()
It was that some packages used metro-config#0.59 and I npm-installed metro-config#0.61 so they were incompatible.

Vue Server Side Rendering: Error in beforeCreate hook: ReferenceError: document is not defined

It happens when add <style></style> in .vue file.
[Vue warn]: Error in beforeCreate hook: "ReferenceError: document is not defined"
I mostly wrote code based on tutorial site.
https://github.com/vuejs/vue-hackernews-2.0/
src/App.vue
<template>
<div class="red">Hello from App.vue</div>
</template>
<script>
export default { name: "App" }
</script>
<style lang="scss" scoped> <-- Without style works well...
.red { color: red; }
</style>
src/app.js
import Vue from 'vue'
import App from './App.vue'
export function createApp() {
let app = new Vue({
render: h => h(App)
})
}
return { app }
}
src/entry-server.js
import { createApp } from './app'
export default context => {
return new Promise((resolve, reject) => {
const { app } = createApp()
resolve(app)
})
}
src/entry-client.js
import { createApp } from './app'
const { app } = createApp()
app.$mount('#app')
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const env = process.env.NODE_ENV || 'development'
const isProd = env === 'production'
const baseConfig = {
mode: env,
devtool: isProd
? false
: 'source-map',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/',
filename: '[name].js'
},
module: {
noParse: /es6-promise\.js$/,
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'style-loader',
'css-loader',
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: ['#babel/preset-env'],
}
},
{
test: /\.(png|jpg|gif|svg|jpeg)$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
},
],
},
performance: {
hints: false
},
plugins: isProd
? [
new VueLoaderPlugin()
]
: [
new VueLoaderPlugin(),
new FriendlyErrorsPlugin()
]
}
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const { merge } = require('webpack-merge')
const VueSSRClientConfig = merge(baseConfig, {
entry: {
app: './src/entry-client.js'
},
resolve: {
alias: {
'create-api': './create-api-client.js',
},
extensions: ['.js', '.vue']
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.VUE_ENV': '"client"'
}),
new VueSSRClientPlugin()
]
})
const nodeExternals = require("webpack-node-externals")
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRServerConfig = merge(baseConfig, {
target: 'node',
entry: './src/entry-server.js',
output: {
filename: 'server-bundle.js',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'commonjs2'
},
resolve: {
alias: {
'create-api': './create-api-server.js',
},
extensions: ['.js', '.vue']
},
externals: nodeExternals({
allowlist: /[\.css|\.scss]$/
}),
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.VUE_ENV': '"server"'
}),
new VueSSRServerPlugin()
]
})
module.exports = [VueSSRServerConfig, VueSSRClientConfig]
setup-dev-server.js
const fs = require('fs')
const path = require('path')
const MFS = require('memory-fs')
const webpack = require('webpack')
const serverConfig = require('./webpack.config')[0]
const clientConfig = require('./webpack.config')[1]
const readFile = (fs, file) => {
try {
return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
} catch (e) {}
}
module.exports = function setupDevServer(app, cb) {
let bundle
let clientManifest
let ready
const readyPromise = new Promise(r => { ready = r })
const update = () => {
if (bundle && clientManifest) {
ready()
cb(bundle, { clientManifest })
}
}
// modify client config to work with hot middleware
clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]
clientConfig.output.filename = '[name].js'
clientConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
)
// dev middleware
const clientCompiler = webpack(clientConfig)
const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfig.output.publicPath,
noInfo: true
})
app.use(devMiddleware)
clientCompiler.hooks.done.tap('done', stats => {
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
if (stats.errors.length) return
clientManifest = JSON.parse(readFile(
devMiddleware.fileSystem,
'vue-ssr-client-manifest.json'
))
update()
})
// hot middleware
app.use(require('webpack-hot-middleware')(clientCompiler, { heartbeat: 1000 }))
// watch and update server renderer
const serverCompiler = webpack(serverConfig)
const mfs = new MFS()
serverCompiler.outputFileSystem = mfs
serverCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
if (stats.errors.length) return
bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'))
update()
})
return readyPromise
}
server.js
const path = require('path')
const express = require('express')
const app = express()
const resolve = file => path.resolve(__dirname, file)
const isProd = process.env.NODE_ENV === 'production'
const { createBundleRenderer } = require('vue-server-renderer')
function createRenderer(bundle, options) {
return createBundleRenderer(bundle, Object.assign(options, {
basedir: resolve('./dist'),
runInNewContext: !isProd,
}))
}
let renderer
let readyPromise
if (isProd) {
const bundle = require('./dist/vue-ssr-server-bundle.json')
const clientManifest = require('./dist/vue-ssr-client-manifest.json')
renderer = createRenderer(bundle, { clientManifest })
} else {
readyPromise = require('./setup-dev-server')(
app,
(bundle, options) => {
renderer = createRenderer(bundle, options)
}
)
}
function render(req, res) {
const context = req.body || {}
const { requestId } = req.body || {}
renderer.renderToString(context, (err, html) => {
// return json
res.json({ requestId, html })
})
}
app.get('/', isProd ? render : (req, res) => {
readyPromise.then(() => render(req, res))
})
app.listen(9991)
Pretty sure that this is to do with your webpack coniguration. I think it's because style loader is trying to inject your styles into the DOM (which obviously is not present on the server side). Hence the reference error.
I'm not 100% sure, but try only using vue-style-loader. There's no need to put it in a chain with style-loader as they are pretty much doing the same thing.
Also run your build command on the project and take a look into the server-bundle. That will show you who's trying to access the DOM.
EDIT:
As a general approach to what you're trying to do, you should also include sass/css in one single rule, like this:
{
test: /\.(sa|sc|c)ss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader']
},
if u have sass pack you can change only webpack.config.js:
module: {
loaders: [{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}, {
test: /\.vue$/,
loader: 'vue'
}, {
test: /\.s[a|c]ss$/,
loader: 'style!css!sass'
}]
},
vue: {
loaders: {
scss: 'style!css!sass'
}
}
> f not installed sass pack:
npm install -D sass-loader node-sass

import { ipcRenderer } from 'electron' produces this error: __dirname is not defined

With this simple vue page:
<template>
<div class="home">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from '#/components/HelloWorld.vue'
import { ipcRenderer } from 'electron'
export default {
name: 'Home',
components: {
HelloWorld
},
data() {
return {
dato: null
}
},
methods: {
rendererFunct () {
//ipcRenderer.on('setting', (event, arg) => {
//console.log(arg);
//})
}
}
}
</script>
The only presence of import { ipcRenderer } from 'electron' produces the error __dirname is not defined :
Is this problem is something related to webpack configuration or it is due to something else?
This is my webpack.config.js :
import 'script-loader!./script.js';
import webpack from 'webpack';
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
target: ['electron-renderer', 'electron-main', 'electron-preload'],
pluginOptions: {
electronBuilder: {
chainWebpackMainProcess: config => {
config.resolve.alias.set('jsbi', path.join(__dirname, 'node_modules/jsbi/dist/jsbi-cjs.js'));
}
},
},
};
module.exports = {
entry: './src/background.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
}
}
module.exports = config => {
config.target = "electron-renderer";
return config;
};
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: 'source', to: 'dest' },
{ from: 'other', to: 'public' },
],
options: {
concurrency: 100,
},
}),
],
};
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},
};
const supportedLocales = ['en-US', 'it'];
export default const config = {
plugins: [
new webpack.ContextReplacementPlugin(
/date\-fns[\/\\]/,
new RegExp(`[/\\\\\](${supportedLocales.join('|')})[/\\\\\]index\.js$`)
)
]
}
This is vue.config.js :
module.exports = {
configureWebpack: {
// Configuration applied to all builds
},
pluginOptions: {
electronBuilder: {
chainWebpackMainProcess: (config) => {
// Chain webpack config for electron main process only
},
chainWebpackRendererProcess: (config) => {
config.plugin('define').tap((args) => {
args[0]['IS_ELECTRON'] = true
return args
})
},
mainProcessFile: 'src/background.js',
mainProcessWatch: ['src/preload.js'],
}
}
}
module.exports = {
pluginOptions: {
electronBuilder: {
disableMainProcessTypescript: false,
mainProcessTypeChecking: false
}
}
}
Electron: version 9.0.0
webpack: version 4.44.1
System:
OS: Linux 5.4 Ubuntu 18.04.4 LTS (Bionic Beaver)
CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU # 4.00GHz
Binaries:
Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
Yarn: 1.22.4 - /usr/bin/yarn
npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
Browsers:
Chrome: 84.0.4147.105
Firefox: 79.0
Looking forward to your kind help.
Marco
__dirname is a NodeJS variable, in recent electron versions, node integration is disabled by default. When opening your BrowserWindow, you should add the following to the options:
webpreferences:{
nodeIntegration: true
}
This is however STRONGLY DISCOURAGED as this opens up security issues.
this seems to solve it for most people (for me sadly enough i now get the next error:
fs.existsSync is not a function)
a better solution i to change your bundler to the correct build mode. You should not be building for node but for web, so target:esnext or something.
if something requires node access, this should be solved by running it in the background thread or the preload scripts.
You can apply the solution described on this post
How to import ipcRenderer in vue.js ? __dirname is not defined
In this way you can call this method from vue files:
window.ipcRenderer.send(channel, args...)
Just make sure you configure preload.js on vue.config.js:
// vue.config.js - project root
module.exports = {
pluginOptions: {
electronBuilder: {
preload: 'src/preload.js' //make sure you have this line added
}
}
}

Can't Resolve Vue Components with # in Storybook

I have setup a new vue project and added storybook to the project. When I have components that use the #/components path, it does not run correctly.
Can't resolve '#/components/EntityGrid/EntityGrid.Component.vue'
I have tried multiple webpack.config.js without any luck. What is the simplest webpack.config.js to fix this
This is happening in the default configuration without a webpack.config.js.
I managed to resolve this issue by adding the following in .storybook/main.js
const path = require("path");
module.exports = {
stories: ['./../src/**/*.stories.(js|jsx|ts|tsx|mdx)'],
...
webpackFinal: async (config) => {
config.resolve.alias = {
...config.resolve.alias,
"#": path.resolve(__dirname, "../src/"),
};
// keep this if you're doing typescript
// config.resolve.extensions.push(".ts", ".tsx");
return config;
},
}
Here are some useful links to help provide further context:
StoryBook docs for webpackFinal - gives you the first clue as to how you might go about configuring your webpack configuration
And then this solution
on an issue in Github provided the final piece of the puzzle
I have no idea what the cause for your issue is, but here is my working vue.config.js
const path = require('path')
module.exports = {
chainWebpack: config => {
config.module
.rule("i18n")
.resourceQuery(/blockType=i18n/)
.type('javascript/auto')
.use("i18n")
.loader("#kazupon/vue-i18n-loader")
.end();
},
configureWebpack: {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': path.join(__dirname, '/src')
}
},
module: {
rules: [
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader',
},
]
},
},
css: {
loaderOptions: {
sass: {
data: `#import "#/assets/sass/_variables.scss"; #import "#/assets/sass/_mixins.scss";`,
}
}
}
}
Just ignore all the stuff that you dont need