I'm using #nuxtjs/i18n plugin with nuxt 3 and after I install it I wrote my i18n(config) in the nuxt.config.ts
my code:
i18n: {
locales: [
{
code: 'fa',
iso: 'fa-IR',
name: 'Farsi',
file: 'fa-IR.json',
dir: 'rtl',
},
{
code: 'en',
iso: 'en-US',
name: 'English',
file: 'en-US.json',
dir: 'ltr',
},
],
defaultLocale: 'fa',
detectBrowserLanguage: false,
langDir: "lang",
vueI18n: {
legacy: false,
fallbackLocale: 'fa',
}
}
after that, I use useLocaleHead({}) and useHead({}) in the default.vue(it's in my layout actually)
<script setup lang="ts">
const head = useLocaleHead({
addDirAttribute: true,
addSeoAttributes: true
});
useHead({
htmlAttrs: {
lang: head.value.htmlAttrs!.lang,
dir: head.value.htmlAttrs!.dir
},
});
</script>
but, when I run the project the dir and locale won't dynamic and change if I select another language.
the output images:
as you can see dir and lang attributes on html tag won't change. however, the content's shown as english.
can anyone help how I can develop it with nuxt3??
Related
I only used Vite with the default settings so far, but now I am trying to migrate an old Vue 2 project to Vue 3 and trying to use Vite instead of webpack.
I have the following vue.config.js (excerpt)
var path = require('path');
module.exports = {
filenameHashing: false,
outputDir: 'src/main/resources/public/clientlibs/vue-dist',
css: {
extract: false,
},
pages: {
'attachments': {
entry: 'src/vue/pages/attachments/main.ts',
chunks: ['chunk-vendors', 'chunk-common', 'attachments'],
},
'base': {
entry: 'src/vue/pages/base/main.ts',
chunks: ['chunk-vendors', 'chunk-common', 'base'],
},
'templates': {
entry: 'src/vue/pages/templates/main.ts',
chunks: ['chunk-vendors', 'chunk-common', 'templates'],
},
},
configureWebpack: {
output: {
libraryExport: 'default',
filename: '[name].js',
chunkFilename: 'chunks/[name].js',
},
resolve: {
alias: {
'#': path.resolve(__dirname, 'src/vue'),
},
},
},
}
Reading the documentation I can use this for the vite.config.js:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: [
{
entry: 'src/vue/pages/attachments/main.ts',
fileName: 'attachments',
},
{
entry: 'src/vue/pages/base/main.ts',
fileName: 'base',
},
{
entry: 'src/vue/pages/templates/main.ts',
fileName: 'templates',
},
]
}
});
But how do I manage to have the chunk-vendors (3rd party plugins) and chunk-common (own shared code) extracted as well with proper tree shaking?
Also relevant how does the rollupOptions look like to have something similar as the configureWebpack section?
I am starting a vue 3 component library which uses a component with a dynamic template.
The dynamic template requires the use of vue/dist/vue.esm-bundler.js. The vue 3 component compiles using vite as long as the following alias fpr
"vue" is included in the vite.config.ts file:
export default defineConfig({
plugins: [vue()],
define: {
global: {},
},
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
'vue': 'vue/dist/vue.esm-bundler.js',
'./runtimeConfig': './runtimeConfig.browser',
},
},
});
However, the same component is used in the vitepress documentation for this library and does not compile. I have added the same alias to the vitepress configuration file:
const path = require('path')
module.exports = {
title: '',
description: '',
themeConfig: {
repo: '',
sidebar: [
{
text: 'Introduction',
items: [
{ text: 'What is My Lib?', link: '/' },
],
}, {
text: 'Components',
items: [
{ text: 'B-Markdown', link: '/components/b-markdown/desc' },
],
}
],
},
vite: {
resolve: {
alias: {
'vue': 'vue/dist/vue.esm-bundler.js'
}
},
}
}
I also tried switching the alias to use
'vue': path.resolve(__dirname, '../../node_modules/vue/dist/vue.esm-bundler.js'),
When compiling the vitepress documentation using either of these vue alias lines, I obtain the following error:
runtime-core.esm-bundler.js:38 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".
at <Anonymous content="Test content." imgFolder="" class="toastui-editor-contents" ... >
at <VRuntimeTemplate class="toastui-editor-contents" style= {max-width: '900px', margin: 'auto'} template="<div><p>Test content.</p>\n</div>" >
at <BMarkdown content="Test content." >
at <Basic>
at <DemoContainer>
at <Components/bMarkdown/desc.md>
at <VitePressContent class="vp-doc _components_b-markdown_desc" >
at <VPDoc key=3 >
at <VPContent>
at <Layout>
at <VitePressApp>
Is this a problem with vitepress not registering the alias?
Currently I'm seeing multiple of the same styling within the dev tools. I'm using React and Laravel Mix and not sure why it's showing the same styling multiple times as I'm using React components importing sass files within the different components but it's not recognising the same css when compiling.
Example:
Expected:
It should only be showing the #media once and the single .side-double once.
Laravel Mix file:
const mix = require('laravel-mix');
const path = require('path');
const glob = require('glob');
const PurgeCSSPlugin = require('purgecss-webpack-plugin');
//-- Website Mix --
mix.babelConfig({
plugins: ['#babel/plugin-syntax-dynamic-import', '#babel/plugin-proposal-class-properties', '#babel/plugin-proposal-optional-chaining'],
});
mix.webpackConfig({
watchOptions: {
ignored: /node_modules/
},
stats: {
warnings: false,
},
output: {
chunkFilename: 'website/js/chunks/[chunkhash].js',//replace with your path
},
resolve: {
alias: {
'#fonts': path.resolve(__dirname, 'resources/website/styles/fonts'),
'#images': path.resolve(__dirname, 'resources/website/images')
}
},
plugins: [
new PurgeCSSPlugin({
paths: glob.sync('website/*', { nodir: true }),
})
]
});
mix.options({
postCss: [
require('autoprefixer'),
],
fileLoaderDirs: {
fonts: 'website/fonts',
images: 'website/images'
}
});
mix.js('resources/website/index.js', 'public/website/js').react();
mix.version();
//-- Website Mix End --
Updated
Definition of style:
Where is the style included:
I've added .scss styling to my site. The .scss files sit next to their .jsx components.
I reference the styles in .jsx like this:
import styles from './guest-card.component.scss'
...
<Card className={styles.card}>
Everything looks great when I run my local server webpack-dev-server --inline --progress --config build/webpack.cold.conf.js
When I build for distributing the app, such as Development machine or QA machine I run npm run build. This builds a dist folder with everything compiled.
When I view my site on a dev/qa server my styles are missing.
Looking in the dist folder I see a /static/css/app.css with my compiled styles. Great! The styles look correct.
My question: What do I do to include these /static/css/app.css in my production site? I tried adding a <link rel="stylesheet" ... to include it and im sure that would work but would give a 404 on my local machine.
Whats the correct way of having styles built
So my question is:
My question is - how do I get my app to reference this new app.css? If I add a
build.js
'use strict';
require('./check-versions')();
process.env.NODE_ENV = 'production';
const ora = require('ora');
const rm = require('rimraf');
const path = require('path');
const chalk = require('chalk');
const webpack = require('webpack');
const config = require('../config');
const webpackConfig = require('./webpack.prod.conf');
const spinner = ora('building...');
spinner.start();
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err;
webpack(webpackConfig, function (err, stats) {
spinner.stop();
if (err) throw err;
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n');
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'));
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'));
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
});
webpack.prod.conf.js
const paths = require('./paths');
const utils = require('./utils');
const webpack = require('webpack');
const config = require('../config');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: require('../config/prod.env');
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].js'),
chunkFilename: utils.assetsPath('js/[id].js')
},
resolve: {
alias: {
settings: `${paths.settings}/dist.js`
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': env
}),
// UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].css'),
// set the following option to `true` if you want to extract CSS from
// codesplit chunks into this main css file as well.
// This will result in *all* of your app's CSS being loaded upfront.
allChunks: false,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
host: '#_host_#',
template: 'index.html',
inject: false,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(paths.nodeModules) === 0
);
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: paths.static,
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
]),
// copy any extra assets to root dist
new CopyWebpackPlugin([
{
from: `${paths.root}\\web.config`,
to: config.build.dist,
ignore: ['.*']
}
])
]
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin');
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
`\\.(${
config.build.productionGzipExtensions.join('|')
})$`
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
webpack.base.conf.js
const paths = require('./paths');
const utils = require('./utils');
const config = require('../config');
module.exports = {
context: paths.root,
entry: {
app: './src/main.jsx'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'#': paths.src,
api: paths.api,
settings: `${paths.settings}/local.js`
}
},
externals: {
bamboraCheckout: 'customcheckout'
},
module: {
rules: [
...(config.dev.useEslint ? [{
test: /\.js$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [paths.src, paths.test],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
}] : []),
{
test: /\.(js|jsx|mjs)$/,
loader: 'babel-loader',
include: [paths.src, paths.test]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
};
webpack.cold.conf.js
const paths = require('./paths');
const merge = require('webpack-merge');
const devWebpackConfig = require('./webpack.hot.conf.js');
module.exports = new Promise(resolve => {
devWebpackConfig.then(base => {
let webpackConfig = merge(base, {
resolve: {
alias: {
api: `${paths.api}/fakes`
}
}
});
resolve(webpackConfig);
})
});
If you miss link to your generated style file in index.html then you should search for problem here, because this plugin is responsible for it
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
host: '#_host_#',
template: 'index.html',
inject: false,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
}
I just looked through plugin documentation, probably you need to remove inject: false. Default is true, and is putting your assets into index.html
I would like to end up with a CSS file that is a merged and minified version of my development environments standard CSS files. With a hashed name based on the content of the file which is automatically added as a tag in my resulting index.html file in my distribution folder.
Is this possible? I assume it is since I've gotten Webpack 4 to do just about everything else I've needed it to do. If it is, how would I go about it?
Mind you, it has to be set up this way. I'm not allowed to use import statements or the like in my JS.
I have tried playing with the Mini Css Extract plugin and Optimize CSS Assets Webpack plugin to see if they could do what I want, but I'm likely doing something wrong as I never get any output file ( I know it wouldn't give me a modified index.html, but having the CSS file would be a start at least).
My current file structure is basically:
'mainFolder'/public/css <- the src css folder,
'mainFolder'/dist/css <- the dist folder where I would like to put the minified file
My config is currently set up like thus:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: [
'./public/js/app.js',
'./public/js/filters/weekday.js',
'./public/js/filters/dial-in.js',
'./public/js/filters/time.js',
'./public/js/filters/group-member.js',
'./public/js/filters/bool-to-icon.js',
'./public/js/filters/date-format.js',
'./public/js/filters/time-format.js',
'./public/js/services/main.js',
'./public/js/configs/config.js',
'./public/js/controllers/main.js',
'./public/js/pages/calendar/controller.js',
'./public/js/pages/company/view/controller.js',
'./public/js/pages/company/edit/controller.js',
'./public/js/pages/group-meeting/create/controller.js',
'./public/js/pages/group-meeting/detail/controller.js',
'./public/js/pages/group-meeting/view/controller.js',
'./public/js/pages/group-meeting-calendar/controller.js',
'./public/js/pages/login/controller.js',
'./public/js/pages/meeting-link/view/controller.js',
'./public/js/pages/meeting-link/edit/controller.js',
'./public/js/pages/meeting-link/detail/controller.js',
'./public/js/pages/user/view/controller.js',
'./public/js/pages/user/edit/controller.js',
'./public/js/lib/angular-semantic-ui.min.js'
],
output: {
filename: 'js/[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist'
},
devtool: 'source-map ',
plugins: [
new CleanWebpackPlugin(['dist'], {
}),
new HtmlWebpackPlugin({
title: 'Zenvite',
template: './public/templates/index.html',
filename: 'templates/index.html'
}),
new CopyWebpackPlugin([
//{ from: 'public/css', to:'css'},
{ from: 'public/media', to:'media'},
{ from: 'public/js/pages', to: 'js/pages', ignore: [ '*.js' ]},
{ from: 'public/templates/app.html', to: 'templates'}
]),
new MiniCssExtractPlugin({
filename: 'app.css',
chunkFilename: '[contenthash].css',
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
publicPath: '../public'
}
},
"css-loader"
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
},
};
Again the optimal result would be having something like [contenthash].css with merged and minified versions of my standard CSS and if possible an added tag in my index.html file.
So far I've got nothing of the sort (except copying the standard files over to the dist directory)
Thanks in advance for any help and if I can answer any questions, feel free to ask.
In the end, when my supervisor realized the import statement was stripped out during compile they allowed it. So we went using that route to achieve what we want. Bellow is ultimately what we went with
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
entry: [
'./public/js/app.js',
'./public/js/filters/weekday.js',
'./public/js/filters/dial-in.js',
'./public/js/filters/time.js',
'./public/js/filters/group-member.js',
'./public/js/filters/bool-to-icon.js',
'./public/js/filters/date-format.js',
'./public/js/filters/time-format.js',
'./public/js/services/main.js',
'./public/js/configs/config.js',
'./public/js/controllers/main.js',
'./public/js/pages/calendar/controller.js',
'./public/js/pages/company/view/controller.js',
'./public/js/pages/company/edit/controller.js',
'./public/js/pages/group-meeting/create/controller.js',
'./public/js/pages/group-meeting/detail/controller.js',
'./public/js/pages/group-meeting/view/controller.js',
'./public/js/pages/group-meeting-calendar/controller.js',
'./public/js/pages/login/controller.js',
'./public/js/pages/meeting-link/view/controller.js',
'./public/js/pages/meeting-link/edit/controller.js',
'./public/js/pages/meeting-link/detail/controller.js',
'./public/js/pages/user/view/controller.js',
'./public/js/pages/user/edit/controller.js',
'./public/js/lib/angular-semantic-ui.min.js'
],
output: {
filename: 'js/app.[contenthash].js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist'
},
devtool: 'source-map ',
plugins: [
new CleanWebpackPlugin(['dist'], {
}),
new HtmlWebpackPlugin({
title: 'Zenvite',
template: './public/templates/index.html',
filename: 'templates/index.html'
}),
new CopyWebpackPlugin([
//{ from: 'public/css', to:'css'},
{ from: 'public/media', to:'media'},
{ from: 'public/js/pages', to: 'js/pages', ignore: [ '*.js' ]},
{ from: 'public/templates/app.html', to: 'templates'}
]),
new MiniCssExtractPlugin({
filename: 'css/app.[contenthash].css'
})
],
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
}]
},
optimization: {
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true, // Must be set to true if using source-maps in production
}),
new OptimizeCSSAssetsPlugin({})
]
}
};