Webpack - Change 'src' path of javascript files in index.html - javascript

I am facing an issue after building my strapi application (using webpack).
After i executed yarn build, my index.html imports javascript files using the <script> tag.
The issue comes here, in my build folder, there are all of my files (images, js files etc...), and 0 subfolder.
But inside my index.html, it imports from an invalid path:
<script src="admin/file.js"></script>
I want to change this src with Webpack to look like that :
<script src="./file.js"></script>
Anybody got a solution ?
Thank you.

Finally, i found the fix.
I am using Strapi for this web app.
Strapi automatically fills webpack with publicPath "/admin/".
However, webpack doesn't understand and put every files (js, img, html) in the same directory, at the same level (no subfolders).
So inside src/admin/, remove the word "example" from the file name "webpack.config.example.js"
Open this file and insert this code
'use strict';
module.exports = (config, _webpack) => {
config = {
...config,
output: { ...config.output, publicPath: './'}
}
return config;
};

Related

Webpack is adding extra code to bundled file (resulting it to throw error after include)

I am setting bundling in my node project with webpack. I have created webpack config file to bundle file. but after including bundle file I got an error.
I am trying to bundle jquery file into output path. I am able to bundle It using below webpack.config.js code.
var path = require('path');
module.exports = {
target: 'web',
output: {
path: path.resolve(__dirname, "./public/javascripts"),
filename: "bundle-jquery.js",
},
entry: './bower_components/jquery/dist/jquery.min.js'
}
Now I am including output path which is bundled into script src replacing jquery. But its not working and I am getting "$ not defined error". By viewing bundled file, I found that there is an extra code added at start into bundled file.
You are doing it completely wrong. If you want jquery in your project, you should import it in your code.
Entry should be your main.js or whatever your entry file is called. Then in main.js do:
import $ from 'jquery' // or use relative path
Webpack will then bundle jquery for you.

Webpack: output.path, publicPath and chunkFilename selecting concept for projects where html and js files are not in the same folder

From the webpack documentation for output.publicPath:
Simple rule: The URL of your output.path from the view of the HTML
page.
module.exports = {
output: {
path: path.resolve(__dirname, 'public/assets'),
publicPath: 'https://cdn.example.com/assets/'
}
};
Above rule is actual for single-page applications, where usually index.html and index.js are in the same folder. However, in the projects of multi page websites, usually special folder like js or scripts is being created. So the file structure of output folder of project could be like:
I tried a lot of combinations of output.path output.publicPath and output.chunkFilename, however still do not understand, how to correctly select the combination of above parameters to make dynamic load works (e. g. const MODULE = import('./loadOnDemand/testModule') which is chunks/chunk__0.js in output folder). Please tell me the concept, how to select output.path publicPath and chunkFilename, which will works for above file system, and also could be scaled on below file system:
Have you tried webpack magic comments to automatically target the chunk names?
https://medium.com/faceyspacey/how-to-use-webpacks-new-magic-comment-feature-with-react-universal-component-ssr-a38fd3e296a
const MODULE = import(/* webpackChunkName: 'test' */'./loadOnDemand/testModule')

Bundle external JavaScript(from a cdn) into a React component

What options are there to bundle an external javascript sdk into a React Component?
I have tried including the javascript in the index.html and referring to it through window.xyz . It works well but I can't do a production build since the javascript is not packaged in this way.
Is there a way to simply import a javascript file into the React Component definition?
PS: React Newbie here !
If you want the script to be bundled in the build, you have 2 options:
1. If the external file is a module, I would approach it as follows:
Download the external JS file and save it somewhere in the project. For example, save it to /utils folder.
Just reference it and use it in the components: import { test } from '/utils/external'
2. If it's not a module:
The same as above - save the file to your project.
The difference is that you have to configure your module bundler to export the globals. This process is called Shimming and here's how to do it with Webpack.
The same as step 2 - import { test } from '/utils/external'
* In both scenarios I assume it's a standalone external file, not being hosted somewhere as a package (npm / bower / etc.). If it's a package, instead of downloading it manually, you should use a package manager.
If you want to load it async (but not bundled):
Follow the #Paras answer, where he suggests for using a library for script async lazy loading.
To load external scripts from a CDN, a good option is to use the react-async-script-loader library. Not only can it load external JS files asynchronously, but it also loads on demand, i.e., lazy loading and supports both parallel and sequential loading.
It allows you to decorate your component using an HOC like so:
export default scriptLoader(
[
'https://cdnjs.cloudflare.com/somelibrary1.min.js',
'https://cdnjs.cloudflare.com/somelibrary2.min.js'
]
)(YourComponent)
Actually you should know about the entire approach then see the codes.
You must make a separate folder for your alternative cdn JavaScript files which they are out of files that webpack build them. Then paste these files into this folder and after all import them as externals into webpack configuration.
Then config them as vendor files, and absolutely output file name should make dynamically, so the webpack build its bundle and then copy your JavaScript files into dist folder. follow below:
// webpack.configuration.js
~~~
module.exports = {
~~~
externals: {
cdnFileOne: `${srcRoot}/outFiles/cdnFile1.js`,
cdnFileTwo: `${srcRoot}/outFiles/cdnFile2.js`,
},
~~~
};
Sounds good, now you have external names for JavaScript files and import it into webpack configuration as a externals config.
Now you should put them in entry to import them as separate files:
// webpack.configuration.js
~~~
module.exports = {
~~~
entry: {
cdnFiles: ['cdnFileOne', 'cdnFileTwo'], <-- cdn files
app: `${srcRoot}/app/index.js`, // <-- its your own codes
},
output: {
path: '/dist',
filename: '[name].js' // <== dynamically make your JavaScript files,
// so, in dist folder you can see app.js and
// cdnFiles.js file
}
~~~
};
Surly, you must add bundles to your HTML template:
~~~
res.status(200).send(`
<!doctype html>
<html lang="en">
<head>
<meta charSet="utf-8" />
${styles}
${title}
</head>
<body>
<div id="root">${ssrHTML}</div>
<script src="app.js" defer></script>
<script src="cdnFiles.js" defer></script>
</body>
</html>
`);
~~~
try something like this:
componentDidMount () {
const script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/somelibrary1.min.js";
script.async = true;
document.body.appendChild(script2);
}

bundling multiple js files

in react using webpack every js files is bundle into a single bundle.js , for my normal html , css, js application for example , i am having 6 libraries. for an example consider
i am using jquery and bootstrap min versions. so if i reference two files the request will be two. so how can i make it into a single file. So there will be a single request.
like when i checked the file size is about in kb's and the request is processed within less that 1 or 2 seconds , like the chrome dev tools shows the time for to load also it parrallely loads the two files.
But how can i bundle the two librarys using webpack and get a single file that i can refer in my application.
i am a beginner to webpack
You need to import them in your entry point file and Webpack will handle the bundling. As you have worked with React, I assume you have basic command line skills.
You can read the Getting Started guide which bundles Lodash like how you are trying to bundle jQuery and Bootstrap.
First of install, ensure that you are installing jQuery, Bootstrap, and any other libraries using npm (or yarn, if you prefer):
# Install Webpack as a dev dependency
npm install webpack webpack-cli --save-dev
# Install dependencies (I've added Popper.js as Bootstrap requires it)
npm install jquery bootstrap popper.js
Create a folder called src and a file inside there called index.js. This is your entry point and Webpack will look for this file unless configured differently. Import the libraries like this:
import $ from 'jquery'
import 'bootstrap'
// Do something with jQuery
$(document).ready(() => console.log('Hello world!'))
Then run Webpack using npx:
npx webpack
A file named main.js should be created in a folder called dist that contains the bundled code. This is your output file. You can use a <script> tag in your HTML file to load this JavaScript:
<!-- assuming your index.html is in the dist folder -->
<script src='main.js'></script>
Once you get here, you can explore more advanced things like importing Bootstrap components individually, minifying code, multiple bundles, transpiling TypeScript, etc.
You will likely need to add a Webpack configuration file very soon as there is only so much that can be done using zero-config mode.
Good practice is to keep two sepearate bundles for the application logic and external libraries and in webpack this can be achieved by the following code,
app.js - appliation index file,
vendors.js - import all external libraries in this file
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
To get a single file, import vendors.js file inside app.js file and give entry key in webpack as
entry: './src/app.js'
Let us assume that you have the files in src directory. You can merge multiple files by specifying them in webpack.config.js to have a single named file as an output. I hope this is what you are looking for.
const path = require('path');
module.exports = {
entry: {
'bundle.js': [
path.resolve(__dirname, 'src/file1.js'),
path.resolve(__dirname, 'src/file2.js')
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [{
exclude: /node_modules/
}]
}
};
As above, the two files "file1.js" and "file2.js" will be combined into a single file "bundle.js" and stored in "dist" directory.
You can also exclude node_modules by specifying a rule in module object of webpack configuration.

Webpack less-loader Missing Base Path on Production Build

I've got a vue-js app that uses webpack. Everything works fine in development and test environments, but I'm having trouble getting it to build for production.
I've got background images in the LESS files. The image files are in /static. (I'm not sure whether that's kosher or if they should be in side src/assets.)
At any rate, when the LESS has something like this:
background-url: url("/static/img/foobar/my-image.svg")
Then the compilted CSS will have the same url
background-url: url("/static/img/foobar/my-image.svg")
When the browser loaders, it can't find that imgate file. The browser is attempting to find the file here:
file:///static/img/foobar/my-image.svg
Can anyone recommend a way to prepend the absolute path when the app builds for production?
Do you have your static assets outside of our project directory in /static ?
Otherwise I don't get why your browser is trying to request it from file:///static/img/foobar/my-image.svg
anyway, your static assets should be part of your repo/project. They do not need to be in src directory, a /static folder within the root of your project is just fine.
when you compile your application - let's say into a dist folder - you should copy the images also in that dist folder. In my app I use the copy-webpack-plugin for that task (I have my images in ./public/assets/img/.. and I reference them as /assets/img/..)
const CopyWebpackPlugin = require('copy-webpack-plugin');
...
plugins: [
...
/** copy all files from the public folder to the compilation root */
new CopyWebpackPlugin([{
from: 'public',
to : ''
}]),
...
also you should make sure that you have the file-loader in place for your static assets. I use it like so:
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\??\#?v=[.0-9]+)?$/,
use : 'file-loader?name=assets/[name].[hash].[ext]'
}
I hope this will help you to resolve your problem.
I ended up moving the images into assets/img and then updating my webpack config to specify the directory using publicPath. Here's what it ended up looking like:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'file-loader',
include: [resolve('src')],
options: {
limit: 10000,
name: '/[name].[hash:7].[ext]',
publicPath: path.resolve(__dirname, 'app')
}

Categories