how to make images directory and sub directory with webpack. - node.js

I am using Nodejs for web application development and webpack as bundler.My code is here:
Directory Structure is:
main.js
src
- js
- styles
- images
-logo.png
-clients_logo
- client_logo1.png
- client_logo2.png
-----------------------------------
public (Use for output)
- js
- css
- images
webpack.config.js
module.exports = {
entry: './main.js',
output: { path: path.join(__dirname, './public/'), filename: './js/bundle.js' },
module: {
loaders: [
{ test: /\.(jpg|jpeg|gif|png)$/,loader:'url-loader?limit=1024&name=images/[name].[ext]' }
]
}
};
main.js
import './src/images/logo.png';
require.context('./src/images/clients_logo/', true);
when I am compile this code using webpack --progress --colors command out put is:
public
- images
- logo.png
- client_logo1.png
- client_logo2.png
But Required out put is:
public
- images
- logo.png
- clients_logo
- client_logo1.png
- client_logo2.png
I am also use
{ test: /\.(jpg|jpeg|gif|png)$/,loader:'url-loader?limit=1024&name=[path][name].[ext]?[hash]&context=/path' }
but it's out put is:
public
- images
- src
- images
- logo.png
- clients_logo
- client_logo1.png
- client_logo2.png
So any one to understand this problem and have solution for it,Please provide it.Thanks

[path] is the relative path of the sources, which in your case is src/images/logo.png and so on for the other images. With context the [path] becomes relative to that path. Setting context=src/ will change that [path] to images/logo.png, which is exactly what you want.
So you can change your config to:
{
test: /\.(jpg|jpeg|gif|png)$/,
loader: 'url-loader?limit=1024&name=[path][name].[ext]&context=src/'
}

Related

Vite: Including files in build output

This is a Vue 3 + Vuetify + TS + Vite + VSCode project.
I'm trying to bundle an XML file in the production build. Some transformation needs to be applied on the file before spitting it out. Found this Vite plug-in that can do transformations. But unfortunately, it doesn't seem to touch XML files in any way. If I put my XML file in public folder, it gets copied to the build output, but is not processed by the transformation plugin. If I put it in assets or somewhere else under src, it is simply ignored.
How can I ask Vite to include certain file(s) in the build output and pass it through transformation?
Note: Before I migrated the project to Vite, I was using Vue 2 and WebPack, where I could use the well-known CopyWebpackPlugin to perform this transformation. Haven't been able to find locate its Vite equivalent till now.
You may want to just write a script to do the transformation and add it to your npm scripts. I created a simple chrome extension to play around with VITE. Having multiple html files was pretty simple:
import { defineConfig, BuildOptions } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
popup: resolve(__dirname, 'popup/index.html'),
options: resolve(__dirname, 'options/index.html'),
},
}
}
})
But I had to create a separate vite config file to process the background script since it had special configuration (didn't want hashing so I could specify the name in my manifest, esm module format), and it takes the typescript and outputs 'background.js' in the public folder:
import { defineConfig } from 'vite'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, 'background.ts'),
output: {
format: "esm",
file: "public/background.js",
dir: null,
}
}
}
})
You could simply have the xml file in your src folder and run a special script (create a 'scripts' folder maybe) to do the transform and store the result in the public folder where vite will pick it up and copy it to the dist folder. Your 'build' script in package.json could look something like this:
"scripts": {
"build": "node scripts/transform-xml.mjs && vite build",
},
Author of the package has introduced a new option named replaceFiles in the version 2.0.1 using which you can specify the files that will be passed through the transform pipeline. I can now do the following in my vite.config.js to replace variables in my output manifest.xml file after build:
const replaceFiles = [resolve(join(__dirname, '/dist/manifest.xml'))];
return defineConfig({
...
plugins: [
vue(),
transformPlugin({
replaceFiles,
replace: {
VERSION_NUMBER: process.env.VITE_APP_VERSION,
SERVER_URL: process.env.VITE_SERVER_URL,
},
...
}),
...
});

Vite library with Windicss

I am using Vite (Vue3) with Windi CSS to develop a library. I am using library mode for the build (https://vitejs.dev/guide/build.html#library-mode) with the following config:
vite.config.js
export default defineConfig({
plugins: [vue(), WindiCSS()],
build: {
lib: {
entry: path.resolve(__dirname, 'src/lib.js'),
name: 'MyLIB',
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue',
},
},
},
},
});
My entry file (src/lib.js) only includes a few Vue components in it and looks like this:
lib.js
export { default as AButton } from './components/AButton/AButton.vue';
export { default as ACheckbox } from './components/ACheckbox/ACheckbox.vue';
import 'virtual:windi.css';
import './assets/fonts.css';
When I build the library I get the js for just those components but the css is for every Vue file in the src folder and not only the ones i included in my lib.js file. I know the default behavior for Windi CSS is to scan the whole src folder but in this case, I only want it to scan the components I added to my entry.
Any ideas?
You should be able to restrict the scan by using extract.include and extract.exclude options, see there : https://windicss.org/guide/extractions.html#scanning
From the doc
If you want to enable/disable scanning for other file-types or locations, you can configure it using include and exclude options

Webpack file-loader with sass-loader

I am new to nodejs and get a problem when trying to use sass with it.
The following information is just fictional, but it represents the
actual condition.
THE SCENARIO:
I have the following folder structure:
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
Goal:
I want to compile the style.scss to style.css using webpack and put it inside dist/frontend/css/ directory, so it should be resulting this path: dist/frontend/css/style.css and create the following folder structure:
dist/
- frontend/
- scss/
- style.scs
- main.js
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
THE CODES:
main.js
import `style from "./scss/style.scss";`
webpack.config.js
module.exports = {
mode: "development",
entry: {
main: "./frontend/main.js"
},
output: {
path: path.join(__dirname, "/dist/frontend"),
publicPath: "/",
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
{
loader: "file-loader",
options: {
name: "css/[name].[ext]"
}
},
"style-loader/url",
"css-loader?-url",
"sass-loader"
]
}
]
}
THE RESULT:
I get this message:
Module not found: Error: Can't resolve './scss/style.scss' in 'E:\project_name\frontend'
THE QUESTIONS
Why is that happening?
What is the correct codes to achieve the Goal?
As the message said, this path is not valid: './scss/style.scss'. There are typo when defining the path. The folder is supposed to be sass instead of scss.
The following configuration will work to achieve the Goal mentioned in the question:
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
"style-loader/url",
{
loader: "file-loader",
options: {
name: "css/[name].css"
}
},
"sass-loader"
]
}
]
}
It works like Mini CSS Extract Plugin, but does not generating additional .js files for each .css file when used to convert multiple .scss files into different .css files.

webpack multiple output path, limit public access, or custom index.html?

I am using node-express, with typescript.
my folder is setup as follows:
.dist
public
public.js
index.html
server.js
node_modules
src
classes
namespace1
module1
public
app - all angular files.
main.ts
routes
index.ts
app.ts
package.json
tsconfig.json
webpack.config.js
Now, I need webpack to output 2 files to /public/public.js and /server.js at .dist folder. nodejs will then run from .dist/server.js, and I want to separate public.js to prevent client to access server.js
I also use html-webpack-plugin to generate html files.
I have tried using a little hack like
entry: {
"server": "./src/app.ts",
"public/public": "./src/public/main.ts"
}
but then html-webpack-plugin made index.html to load script from /public/public.js instead of public.js
Now, I think we can solve this in 3 way.
Let server.js send public.js using http://localhost/public.js, but it will make managing static folder a little bit complicated. but I will think some way to trick it. Question: how to serve public.js via server.js?
Set entry to "public": "./src/public/main.ts". Question: how to put that public.js into public folder?
Setup html-webpack-plugin to load from /public.js instead of /public/public.js and make index.html inside /public folder. As of now, html-webpack-plugin generates <script type="text/javascript" src="../public/polyfill.js"></script><script type="text/javascript" src="../public/public.js"></script></body> where is should make <script type="text/javascript" src="/polyfill.js"></script><script type="text/javascript" src="/public.js"></script></body>
Question: How to do that?
Or is there any other idea to solve this? I am open to any suggestion.
Thank you
I think I can answer scenarios 2 and 3.
2- Apart of setting up entry points, you can set up some output configuration. http://webpack.github.io/docs/configuration.html#output
3- Also you could use copy webpack plugin to copy the files you need into your public folder.
https://github.com/kevlened/copy-webpack-plugin
I do it in one of my projects, this is the code that I add on the webpack config file:
new CopyWebpackPlugin([
{from: __dirname + '/src/public'}
])
Hope this helps.
Regards.
I managed by using this config.
module.exports = [
{
entry: "./src/app.ts",
output: {
filename: "server.js",
path: __dirname + "/dist"
},
target: "node",
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx']
},
node: {
__dirname: false
},
module: { // all modules here for server
}
}, {
entry: "./src/public/main.ts",
output: {
filename: "bundle.js",
path: __dirname + "/dist/public"
},
target: "web",
plugins: [
new htmlPlugin({
filename: 'index.html'
})
],
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx']
},
module: { // all your modules here.
}
}
]

Building ReactJS Project with Webpack causes graceful-js to report error "can't resolve 'fs'"

I was building my project last night. It's a Node project building React distributable frontend code with webpack. When I was done, I shut down my computer. I turned on my computer this morning and now, with no code or config changes to my knowledge, I get errors that some kind of dependency of a dependency is missing.
ERROR in ./~/fsevents/~/graceful-fs/fs.js
Module not found: Error: Can't resolve 'fs' in '/Users/stevenkitzes/Documents/Career Dev/C2 to A1/react-lnl/demo/react-lnl/node_modules/fsevents/node_modules/graceful-fs'
# ./~/fsevents/~/graceful-fs/fs.js 3:9-22
# ./~/fsevents/~/graceful-fs/graceful-fs.js
# ./~/fsevents/~/fstream/lib/reader.js
# ./~/fsevents/~/fstream/fstream.js
# ./~/fsevents/~/tar-pack/index.js
# ./~/fsevents/~/node-pre-gyp/lib/package.js
# ./~/fsevents/~/node-pre-gyp/lib ^\.\/.*$
# ./~/fsevents/~/node-pre-gyp/lib/node-pre-gyp.js
# ./~/fsevents/fsevents.js
# ./~/chokidar/lib/fsevents-handler.js
# ./~/chokidar/index.js
# ./~/watchpack/lib/DirectoryWatcher.js
# ./~/watchpack/lib/watcherManager.js
# ./~/watchpack/lib/watchpack.js
# (webpack)/lib/node/NodeWatchFileSystem.js
# (webpack)/lib ^.*$
# (webpack)/lib/webpack.js
# ./jsx-map/jsx-build.js
Here is my webpack config file:
var webpack = require('webpack');
var path = require('path');
var APP_DIR = path.resolve(__dirname, '.');
var plugins = [];
var config = {
entry: APP_DIR + '/jsx.js',
output: {
path: APP_DIR,
filename: 'jsx-out.js'
},
module: {
loaders: [
{
test: /\.jsx?/,
exclude: /node_modules/,
include: APP_DIR,
loader: 'babel-loader',
query: {
presets: ['react']
}
}
]
},
plugins: plugins
};
module.exports = config;
It sounds like you may be trying to bundle both server-side (node) and client-side (react stuff) with webpack. If so you need to bundle them separately to create 2 different bundle files.
One for node for your to exeucte e.g., node bundle-server.js (assuming your server-side bundle is generated as 'bundle-server.js')
Another for inclusion into your front-end html code, e.g., <script src='./bundle-client.js'></script> (assuming your client-side bundle is generated as 'bundle-client.js').
Specifically you need to set options in your webpack config file to have two 'output' and two 'target', one for server-side, and another for client-side.
For details on doing client-side and server-side bundling with webpack, you can refer to https://medium.com/code-oil/webpack-javascript-bundling-for-both-front-end-and-back-end-b95f1b429810

Resources