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?
Related
I'm trying to put an image as background in a div but it doesn't recognize it because webpack changes the path to http://localhost:8080/gaia.png instead of http://localhost:8080/assets/images/gaia.png
The image is displayed correctly inside an tag but it doesn't load if I want to use it from the Css file.
I'm sure the problem is the file path but I don't know how to fix it.
index.js
import './assets/style/style.css'
import './assets/images/gaia.png'
import './assets/fonts/CascadiaCode.ttf'
const fun = () => {
console.log('hey')
}
fun();
webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src', 'index.html')
})
],
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator: {
filename: '[name][ext][query]',
outputPath: 'assets/images/',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: '[name][ext][query]',
outputPath: 'assets/fonts/',
},
},
],
},
};
style.css
.container {
width: 300px;
height: 300px;
background-image: url("../images/gaia.png");
background-size: auto;
}
delete outputpath and set it up as :
generator: {
filename: 'assets/images/[hash][ext][query]'
}
}
I fixed the problem by installing a specific loader for Html images
npm install --save-dev html-loader image-webpack-loader
I followed this tutorial: Optimizing Static HTML And Images With Webpack
Here is my webpackconfig.js file:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
static: './dist',
},
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src', 'index.html'),
}),
],
module: {
rules: [
{
test: /\.css/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.html$/i,
use: 'html-loader',
},
{
test: /\.(png|jpg)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name]-[hash][ext]',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name]-[hash][ext]',
},
},
],
},
};
I also created a Webpack Template that you can use with the default configuration on my GitHub:
Webpack Template Repo
Simple webpack setup, when I use import to load my scss it is completely missing from the bundle. The line where the import should be is simply missing. When I use require instead, it works.
optimization: {usedExports: true} is not the problem, I tried with and without
mini-css-extract-plugin also did not work.
when I put a typo in the scss it complains, so it is parsed but simply not bundled in the end?
index.js
require("./scss/style.scss");
//import "./scss/style.scss" <--- not working
import { createApp } from 'vue';
import App from './components/App.vue';
const el = document.getElementById('app');
createApp(App).mount(el);
webpack config
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const { DefinePlugin } = require('webpack');
const dist = path.resolve(__dirname, "dist");
module.exports = env => {
const mode = env.production == true ? "production" : "development";
const devtool = mode == "production" ? false : "inline-source-map";
return {
mode: mode,
entry: './web/index.js',
output: {
filename: 'bundle.js',
path: dist
},
optimization: {
usedExports: true,
},
devServer: {
static: {
directory: dist
},
port: 8888
},
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
}, {
test: /\.(ttf|eot|woff|woff2|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
},
},
}, {
test: /\.vue$/,
loader: 'vue-loader'
}]
},
plugins: [
new CleanWebpackPlugin(),
new DefinePlugin({
__VUE_OPTIONS_API__: false,
__VUE_PROD_DEVTOOLS__: false,
}),
new HtmlWebpackPlugin({
template: path.resolve("./web/index.html")
}),
new VueLoaderPlugin()
],
resolve: {
extensions: ['.js'],
alias: {
"#": path.resolve(__dirname, 'web')
}
},
devtool
};
};
I found the problem but I don't understand why webpack drops it.
Quote from https://webpack.js.org/guides/tree-shaking/
Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode:
In my package.json I put
"sideEffects": false,
to be able to use treeshaking.
But I had to disable it in the loader rule
{
test: /\.(sa|sc|c)ss$/,
use: ['style-loader','css-loader','sass-loader'],
sideEffects: true <----
}
I'm new to React development and I try to use webpack to set up my project. Unfortunately, I have a problem with my configuration: with it, components from node_modules don't apply styles no matter if I try to build the application or to start it with webpack-dev-server.
My webpack.config.js:
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.jsx',
output: {
filename: 'main.js',
path: path.join(__dirname, 'dist')
},
resolve: {
extensions: ['.js', '.jsx']
},
plugins: [
new HtmlPlugin({
template: './src/index.html'
})
],
module: {
rules: [
{
test: /\.jsx?/i,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/i,
use: 'css-loader'
},
{
test: /\.(png|jpe?g|ttf|svg)/i,
use: 'file-loader'
},
]
},
devServer: {
port: 9000,
contentBase: path.join(__dirname, 'dist')
}
}
.babelrc:
{
"presets": ["#babel/preset-react"]
}
UPD: I didn't mean the styles I wrote, but the styles of the components themselves. For example, Button component of the primereact renders like the default html button.
I'm having some issues. I keep getting this error
Module parse failed: Unexpected character '#' (1:0) You may need an
appropriate loader to handle this file type, currently, no loaders are
configured to process this file. See
https://webpack.js.org/concepts#loaders
#import url("https://cloud.typography.com/7374818/6819812/css/fonts.css");
I've tried some of the suggested solutions I've found online and none seems to work.
This is what my Webpack config looks like
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
entry: {
main: path.resolve(__dirname, './src/App.tsx'),
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'public'),
sourceMapFilename: "[name].js.map"
},
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
include: [
path.resolve(__dirname, './src'),
],
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react', '#babel/preset-typescript'],
},
},
{
test: /\.(scss|css)$/,
include: path.resolve(__dirname, './src'),
use: [
MiniCssExtractPlugin.loader,
'style-loader',
'css-loader',
{
loader: "postcss-loader",
options: {
plugins: () => [
require("autoprefixer")()
],
},
},
'sass-loader',
],
},
{
test: /\.(png|woff|woff2|eot|ttf|otf|svg)$/,
loader: 'url-loader',
options: {
limit: 100000,
}
},
],
},
resolve: {
extensions: ['.js', '.jsx', 'json', 'ts', 'tsx', '.scss'],
alias: {
src: path.resolve(__dirname, './src/'),
},
},
devServer: {
historyApiFallback: true,
contentBase: './public',
port: 3030,
open: true,
compress: true,
hot: true,
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
plugins: [
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin(),
],
};
The component looks like this. uilib is a local dependency I'm linking using yarn link
import React from 'react';
import ReactDOM from 'react-dom';
import { Header, Footer } from 'uilib';
import 'uilib/index.css';
export const App: React.FC<{}> = () => (
<>
<Header/>
<div>Hello in oct</div>
<Footer/>
</>
);
ReactDOM.render(
<App />,
document.getElementById('root'),
);
The uilib/index.css looks like this
#import url("https://cloud.typography.com/7374818/6819812/css/fonts.css");
.header {
height: 70px;
}
I feel that ulib folder is perhaps not inside src directory.
Can you try changing your webpack loader config for scss|css to be like so:
{
test: /\.(scss|css)$/,
include: path.resolve(__dirname) // <---- leave it __dirname or remove the prop completely
....
....
}
I am hoping this will let webpack look at project's root which can help it parse the file accordingly.
Also, unless ulib is in node_modules, you can exclude it from loader with exclude: 'node_modules'
Thank you guys for reading my question. Really hoping for a solution to this, I've been trying to find a fix for days to no avail.
Here's the rundown: My goal is to render a React application on the server-side using .NET Core. I haven't even started with the react part yet, right now I'm simply trying to render an h1 tag with the ASP.NET Javascript Services Prerendering functionality.
On my first iteration, I wrote my boot-server.js file with es5 and it worked perfectly. However, I quickly realized I was going to need to compile the file through webpack in order for it to understand my React code.
As soon as I piped that file through webpack though, I got a "window is not defined" error which I haven't been able to fix. I understand that part of my application should not be aware of the window object since it lives in the server but setting the webpack config's target field to node does not seem to fix the issue. Below are all the files involved.
Here is my boot-server.js file:
import { createServerRenderer } from 'aspnet-prerendering';
module.exports = createServerRenderer((params) => {
return new Promise((resolve, reject) => {
var html = '<h1>Hello world!</h1>';
resolve({
html: html
});
});
});
Here is my cshtml view:
#addTagHelper "*, Microsoft.AspNetCore.SpaServices"
<app id="root" asp-prerender-module="wwwroot/client/boot-server.bundle">Loading...</app>
Here is my webpack.config.js file:
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const path = require("path");
const clientConfig = {
entry: './FrontEnd/index.js',
output: {
path: path.resolve(__dirname, "wwwroot/client"),
filename: "client.min.js",
publicPath: "/client/"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["es2015", "react", "stage-0"],
plugins: ["transform-class-properties", "transform-decorators-legacy", "react-html-attrs"]
}
}
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader?name=[name]_[hash:8].[ext]'
]
}
]
},
mode: 'development',
devServer: {
contentBase: './wwwroot/client',
hot: true
}
};
const bootServerConfig = {
stats: { modules: false },
resolve: { extensions: ['.js'] },
output: {
filename: '[name].js',
publicPath: '/wwwroot/client/', // Webpack dev middleware, if enabled, handles requests for this URL prefix
libraryTarget: 'commonjs'
},
entry: {
'main-server': './FrontEnd/boot-server.js'
},
module: {
rules: [
{
test: /\.js$/,
include: /FrontEnd/,
use: [
{
loader: "babel-loader",
options: {
presets: ["es2015", "react", "stage-0"],
plugins: ["transform-class-properties", "transform-decorators-legacy", "react-html-attrs"]
}
}
]
},
{
test: /\.svg$/,
use: {
loader: 'url-loader',
options: { limit: 25000 } //?limit=100000'
}
}
]
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './wwwroot/client')
},
target: 'node'
}
module.exports = [clientConfig, bootServerConfig];
Here is a screenshot of the error page: