Webpack bundled JS not being executed - javascript

This is a very strange problem because actually, some of the bundled code is being executed. I use style loader for my CSS and that of course gets put into bundle.js and loads and works fine. However, I also have a file with some code to set up the jQuery localScroll plugin, and that code isn't working.
To test it, I included in the same file a call to console.log(), just telling it to write the number 4. If I open up bundle.js, I can see the console.log() call as well as the call to $.localScroll(), they just simply aren't running. Calling $.localScroll() manually from the console works as intended.
Here is the JS file in question:
console.log(4);
$(() => {
$.localScroll({duration: 800});
});
Here is my Webpack config:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './webpack-entry.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new webpack.optimize.UglifyJsPlugin()
],
output: {
filename: './javascripts/bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|jpeg)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192,
fallback: 'file-loader',
name: './images/[hash].[ext]'
}
}
},
{
test: /\.pug$/,
use: [
{
loader: 'file-loader',
options: {
name(file) {
if(new RegExp(/partials/).test(file)) {
return './views/partials/[name].[ext]'
}
return './views/[name].[ext]'
}
}
},
'pug-asset-loader?root=./src'
],
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['env'],
}
},
]
}
],
}
};
Finally, here is bundle.js (my custom code seems to be at the very bottom, in some sort of array of functions). The non-uglified version is too long for SO, so here it is on Hastebin: https://hastebin.com/vululimupi.js

The problem is that you haven't defined this dependency as a module. Rewriting it following supported module format specs should help.

After some testing, it seems that the essential problem is just as #uKolka was saying - my files were not getting required as modules. While I'm still not entirely certain why their code was still appearing in my bundle file but not running, I have found a way to still reap the recursive benefits of require.context(). It seems that require.context() returns a function which is itself capable of resolving the files it logs in whatever folder you have pointed it at. It also has a member function keys() which quite conveniently returns each dependent file name and is easily used with forEach().
Given all that, this is how my webpack-entry.js looks now:
import './src/stylesheets/scss/master.scss';
require.context('./src/views', true, /\.pug$/);
const js = require.context('./src/javascripts/', false, /\.js$/);
js.keys().forEach(key => js(key));
This works just fine.

In my case it was due to Babel and React. If you use React, then try to call ./src/index.js directly and use "#babel/preset-env", "#babel/preset-react" in your .babelrc. You can take a look at my gist. and in your webpack.config.js:
{
test: /\.js?$/,
use: ["babel-loader"],
exclude: /node_modules/
},
take a look at the gist:
https://gist.github.com/Nagibaba/14e898d99a4be89b00a60d28abc19bc0

For ruby's rails/webpacker users only.
This question title and content made me find it before this issue which may be the correct answers for some users here. To avoid link rot, I'll explain it shortly below:
Make sure your #rails/webpacker npm library and webpacker gem both have the same exact version.
I ended up doing:
IO.foreach("package.json").find { |line| line[%r("#rails/webpacker": "(.*?)")]}
gem "webpacker", Regexp.last_match(1).tr("-", ".")

Related

Building an AngularJS and Vue.js into one app using webpack?

This may seem a bit convoluted, and potentially the answer is "don't do it that way, do it this way" so I'll start with the background of what I am doing. Basically I have a legacy AngularJS app that we want to migrate away from and towards Vue. We do not have the option to end-to-end rewrite the app, and need to do it piece by piece whilst still delivering a functional app.
The general goal is to therefore have both frameworks running simultaneously, my hope is that I can either do something with the routing or potentially split my single page app into 2 seperate pages for the different fraweworks. I have converted the angularjs from using a gulp build pipeline to using webpack as I assumed this was a logical first step to getting Vue to run, but now I have hit a road block.
My working webpack.config.js for building the angular app looks like the following:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
target: 'web',
// mode: "development",
// devtool: "source-map",
module: {
rules: [
{
test: /\.html$/,
loader: "html-loader",
},
{
test: /\.s[ac]ss$/i,
use: [
"style-loader",
"css-loader",
"sass-loader",
],
},
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
}
],
},
entry: {
vendor: "./source/vendor.js",
main: "./source/index.js",
},
optimization: {
minimize: false
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'distribution'),
clean:true
},
plugins: [
new HtmlWebpackPlugin({
template: 'source/index.html',
})
]
};
this now works fine and I get something out add the end that works as it did before.
I then added a /source/vueJs directory, and copy & pasted the content hello world project that is generated by vue create hello-world. My assumption was if I could modify my webpack.config.js to build this, I could then iterate on it further to get to a point where it merged the two working apps together, but I'm already struggling to get the hello-world vue project to produce anything.
So far I basically commented out all the relevant angularJS parts, and added what I thought was correct to get the vue app to build, so now I have this:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
target: 'web',
mode: "development",
devtool: "source-map",
module: {
rules: [
// {
// test: /\.html$/,
// loader: "html-loader",
// },
// {
// test: /\.s[ac]ss$/i,
// use: [
// "style-loader",
// "css-loader",
// "sass-loader",
// ],
// },
// {
// test: require.resolve("jquery"),
// loader: "expose-loader",
// options: {
// exposes: ["$", "jQuery"],
// },
// },
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
// this will apply to both plain `.js` files
// AND `<script>` blocks in `.vue` files
{
test: /\.js$/,
loader: 'babel-loader'
},
// this will apply to both plain `.css` files
// AND `<style>` blocks in `.vue` files
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
],
},
entry: {
// vendor: "./source/vendor.js",
// angular: "./source/index.js",
vue: "./source/vueJs/index.js"
},
optimization: {
minimize: false
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'distribution'),
clean:true
},
plugins: [
new HtmlWebpackPlugin({
//template: 'source/index.html',
}),
new VueLoaderPlugin()
],
};
this runs fine and I get a distribution/ directory with my assets in, but the served site runs as if there is no javascript running at all. Comparing the output of npx webpack on my version and the output of npx vue-cli-service build on the hello-world project, the javascript is similar but different in a lot of key areas, for a start it seems as though my version does not have any HTML embedded in it like the hello world project does.
Is it a lost cause trying to compile a vue app from webpack? Can you only do it using vue-cli-service build and therefore limited to vue only? I tried modifying my vue.config.js using the info found at https://cli.vuejs.org/guide/webpack.html & https://cli.vuejs.org/config/, but frankly I feel I am out of my depth at this point and unsure if what I am doing is even a good idea.
Is there a better strategy to take to get to my end goal? If this is a workable solution, what do I need to change about my configs to get both the angularjs and the vue app to build properly?
I wasn't seeing the wood for the trees. The problem isn't that that webpack.config.js doesn't succesfully producing a working angular & vue combined app, the problem is that I'm not providing a template that actually uses either of these things, so it just produces a blank index.html with the scripts provided but no content in the body.
Changing the
new HtmlWebpackPlugin({
//template: 'source/index.html',
}),
in my question to have a template that uses both an AnularJS component and a Vue component worked fine.

CSS images not copied to output folder in Webpack

I am using Webpack to bundle a number of js/css files in a site. I am bundling bootstrap.css and chosen.css as part of my bundles. In order to create the bundles, I have a main.js that I am using as an entry point to import all the other files that I will need. I am using file-loader to process font and image files and move them to the appropriate directories. I am using the ExtractTextPlugin with the css-loader and resolve-url-loader to create a separate css bundle from my js bundle.
My main.js is:
import 'bootstrap/dist/css/bootstrap.css';
import 'chosen-js/chosen.css';
import './datetimehelper.js';
import './deletelink.js';
import './dropdown.js';
My webpack.config.js is:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/js/main.js',
output: {
filename: 'wwwroot/js/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[name].[ext]',
outputPath: 'wwwroot/'
}
}
]
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
outputPath: 'wwwroot/'
}
}
]
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?url=false', 'resolve-url-loader'],
publicPath: '../'
})
}
]
},
plugins: [
new ExtractTextPlugin({
filename: 'wwwroot/css/bundle.css'
})
]
};
With the above configuration, the font references in bootstrap.css are picked up, moved to the appropriate directory and the urls are fixed in the css bundle that is emitted. However, the images that are referenced in chosen.css are not being picked up. Can anyone tell me what I need to do to make the images work correctly? I've tried replacing file-loader with url-loader and no change. I've also tried importing the images in my main.js and they were moved, but the urls in the css bundle were not rewritten correctly.
Having path configured in output makes life a lot easier. That would serve as the base output folder and all other loaders/plugins can work relative to that. May be the files were copied but not to your intended directory. Please do take a look at WebpackBootstrap repo. The config copies as well as converts image paths properly.
I finally figured it out. In the rules, I had:
{
test: /\.css$/,
use: ExtractTextPlugin.extract('css-loader', 'resolve-url-loader')
}
Instead, it should be:
{
test: /\.css$/,
loader: ExtratTextPlugin.extract('css-loader', 'resolve-url-loader')
}
Not sure what the difference is between use and loader because I'm fairly new to Webpack, but in this case it makes all the difference.

Webpack string replace loader not working

I'm bundling my project with webpack. In order to manipulate some of the files I've to replace specific values in a certain node-module. To achieve that I'm using the string-replace-loader. I added the following code to my webpack config without success.
{
test: /\.js$/,
loader: 'string-replace',
query: {
search: '[MouseEvent]',
replace: '[]'
}
}
In the bundeld file the string is not replaced. The files are within the folder node_modules/ng2-bootstrap. so may i have to specify this as well?
you should use include: [/node_modules\/module_name/] because webpack by default exclude node_modules.
But while reading an issue for similar problems, probably you must use "exclude, include" like this:
{
test: /\.js$/,
loader: 'string-replace',
exclude: /node_modules(?!\/module_name)/
query: {
search: '[MouseEvent]',
replace: '[]'
}
}
if you want read the issue, go here.
EDIT AFTER COMMENTS:
after some tried, i've done this (with an other plugin, but seems like yours), i've done that with this code:
preLoaders: [
{
test: /\.js$/,
loader: StringReplacePlugin.replace({
replacements: [
{
pattern: /.*?(react).*?/ig,
replacement: function (match, p1, offset, string) {
console.log("found");
return "found";
}
}
]}),
include: /node_modules\\react.*/
}
],
it might works on loaders, i've but on preloaders because i already have a loader for js.
Note that the error was on regex of include/exclude

UglifyJs with webpack just freezes when doing production build

I'm using Webpack, and when I run a production build ie.
webpack -p
The build never completes.
A quick search says to disable the sourcemap for uglifyjs... but I cannot find a decent explanation on how to do this.
Ideally I would be able to disable the sourceMap from from the configuration.
Finally, this brings up another question which is... shouldn't I want a source map when I create a production build? Disabling the feature seems like a poor workaround.
module.exports = {
entry: ["./utils", "./app.js" ],
output: { filename: "bundle.js" },
module:{
preLoaders:[
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'jshint-loader'
}
],
loaders: [
{
test:/\.es6$/,
exclude: /node_modules/,
loader: "babel",
query: {
presets: ['es2015']
}
}
]
},
resolve: {
extensions: ['', '.js', '.es6']
},
watch: true
}
UPDATE: Ok... it looks as if the watch: true portion of my config was the culprit... but still, it would be good to know how to disable sourceMaps.
This is from #user104317 above, in the comments section.
"Watch" tells webpack to keep running and automatically build your files as they change. The build finished. The command will keep running till killed.

How to configure font file output directory from font-awesome-webpack in webpack?

I just installed font-awesome-webpack. I import it using: require("font-awesome-webpack");
My webpack config includes the following in my module loaders array:
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
Problem is I am getting this error in developer console:
localhost/:1 GET http://localhost/mysite/app/db812d8a70a4e88e888744c1c9a27e89.woff2
localhost/:1 GET http://localhost/mysite/app/a35720c2fed2c7f043bc7e4ffb45e073.woff
localhost/:1 GET http://localhost/mysite/app/a3de2170e4e9df77161ea5d3f31b2668.ttf 404 (Not Found)
The problem is, those files are created at the root (within the mysite directory). How do I configure such that those woffs and ttf are output within the mysite/app directory?
I've recently wanted to use font awesome with webpack v1, I've installed the npm module font-awesome not font-awesome-webpack
You must install few loaders before :
npm i css-loader file-loader style-loader url-loader
and add use them in your webpack.config.js :
module: {
loaders: [{
test: /\.css$/,
loader: 'style!css?sourceMap'
}, {
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff"
}, {
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff"
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/octet-stream"
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: "file"
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=image/svg+xml"
}]
}
Now if you include in your entry.js :
require('font-awesome/css/font-awesome.css');
You normally be able to use font-awesome in your template :
<i class="fa fa-times"></i>
This gist helped me : https://gist.github.com/Turbo87/e8e941e68308d3b40ef6
As of Feb. 2016 this seems to be a common question with webpack, so I hope this provides some help. If you add this to the loader: '&name=./path/[hash].[ext]', that specifies where to look for those files. For example:
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff&name=./[hash].[ext]'
}
This places the correct URL to the fonts within the generated CSS file.
I recommend this method when dealing with anything other than css/scss. Hope this helps.
In addition to the above answers, I
I had to specify a path in output to get it working like so to specify the hosted location and not write the assets to the root path:
output: {
filename: "./bundle.js",
path: “./client”
},
module: {
loaders[
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff&name=./webpack-assets/[name]/[hash].[ext]"
}, {
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff&name=./webpack-assets/[name]/[hash].[ext]"
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/octet-stream&name=./webpack-assets/[name]/[hash].[ext]"
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: "file?&name=./webpack-assets/[name]/[hash].[ext]"
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=image/svg+xml&name=./webpack-assets/[name]/[hash].[ext]"
}
] // loaders
} // module
{
test: /\.(png|woff|woff2|eot|ttf|svg)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader?limit=100000'
}
This schema helped me
This is my case, because of my script path is like below:
script(src='/javascripts/app.js')
So, I have to add '&name./javascripts/[hash].[ext]' to all font files like:
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff&name=./javascripts/[hash].[ext]"
}, {
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff&name=./javascripts/[hash].[ext]"
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/octet-stream&name=./javascripts/[hash].[ext]"
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: "file?name=./javascripts/[hash].[ext]"
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=image/svg+xml&name=./javascripts/[hash].[ext]"
}
Just as a note, I came across a similar fault using the font-awesome-loader.
Where the directory would not be set correct, regardless of any of the changes above.
To correct this, the option publicPath can be added to output:
output: { path: config.outputPath, filename: '[name].js', publicPath: '/assets/' },
The folder /assets/ will be changed to wherever you actually store your fonts.
Hopefully this helps.
I had font-awesome-webpack working on my PC, but it wouldn't work on my Mac. I think my PC was still throwing the 404s for the .woff2, .woff, and .tiff, but the icons displayed properly, so I ignored the problem.
My Mac, however, would not display the icons. While reading this Q&A, I tried a bunch of things. Here's what lead to my solution:
On my http://localhost:8080/View/ page, I was getting 404s that looked like the link below:
I entered http://localhost:8080/View/e6cf7c6ec7c2d6f670ae9d762604cb0b.woff2 into the browser, and confirmed the 404.
I tried going to http://localhost:8080/e6cf7c6ec7c2d6f670ae9d762604cb0b.woff2 (removing the extra path before the font file), and was able to access the file.
I modified Paul's answer to remove the . that made the file request relative.
For example, Paul suggested:
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&minetype=application/font-woff&name=./[hash].[ext]'
}
Take note of the &name parameter, that uses ./[hash].[ext]. I dropped the leading . and now there are no 404s (the browser correctly requests the files from the root of the site):
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&minetype=application/font-woff&name=/[hash].[ext]'
}
Conclusion: If your entry point is NOT at your web root, and you're able to access the font files at the web root, you probably just need to use this name configuration to fix the path.
Same issue faced.
Fixed it using the below syntax,
loader: "file?name=./fonts/[hash].[ext]"
fonts is the directory name, replace it with your own directory name.
Example:
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "url?name=/build/[hash].[ext]&limit=8192&mimetype=application/font-woff"
}

Categories