--- UPDATE ---
Error disappeared when setting NODE_ENV=production before my webpack build-step. I still don't know what the underlying cause for this issue was.
--- END UPDATE ---
I have made a Phonegap app using Webpack. The app works fine on iOS and other Android devices, but it crashes on a Huawei Honor H60-L04 with Android 4.4.2. It crashes on load, showing this error:
Uncaught SyntaxError: Unexpected token >
By adding/removing all scripts loaded in index.html one by one, I have isolated the problem to exist in the dist/build.js file. That is the resulting js file from Webpack build, with all the app logic inside. Is there some webpack config mistake causing this issue? And why is only this device getting the error?
If relevant, I am using Vue.js and Framework7 to develop the app, and Phonegap Build to build it.
--- UPDATE --- :
When remote debugging the console says the error is at line 85 in index.html, but the index.html is not that long. Guessing that line number reports that way because dynamic things are added to the html-file when trying to load script.
My entire .babelrc file:
{
"plugins": ["transform-es2015-shorthand-properties"]
}
My entire Webpack config file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
performance: {
hints: false
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
sass: "vue-style-loader!css-loader!sass?indentedSyntax"
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue',
'Framework7Vue': path.join(__dirname, '/node_modules/framework7-vue/dist/framework7-vue.min.js')
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
--- END UPDATE ---
Related
today I've noticed a strange bug (or I am to dumb?) with my webpack-dev-server.
I've got a Spring Boot App with thymleaf templates. Some pages may only load one others may have more than one js-file:
// main.js
import "../style.scss";
single.html:
<body>
<script th:src="#{/myapp/js/main.js}"></script>
</body>
multiple.html
<body>
<script th:src="#{/myapp/js/main.js}"></script>
<script th:src="#{/myapp/js/other.js}"></script>
</body>
I've splitted my config into a dev, production and common part:
webpack.common.js:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
main: path.resolve(__dirname + "/src/main/js/main.js"),
other: path.resolve(__dirname + "/src/main/js/other.js"),
},
output: {
path: path.resolve(__dirname, "./src/main/resources/static/myapp"),
filename: "js/[name].js",
},
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
// prettier-ignore
["#babel/preset-env", {
corejs: "3.6.4",
// debug: true,
useBuiltIns: "usage"
}
],
],
},
},
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name].css",
}),
],
};
webpack.dev.js
const common = require("./webpack.common");
const { merge } = require("webpack-merge");
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
devServer: {
proxy: {
"/": "http://localhost:8081",
},
port: 8083,
devMiddleware: {
publicPath: "/myapp",
},
},
});
The strange behaviour: If I'm editing files for the page which only a single script has been loaded (single.html), changes are applied immediately. For example changing the background color in the css file is displayed without pagereload. If I'm editing a page where multiple scripts (entry points) are used this is not working anymore. My dev-console logs the following:
[HMR] Update failed: Loading hot update chunk global failed.
(missing: http://localhost:8083/myapp/main.618757b0411fc5552e94.hot-update.js)
The first entry point / chunk (main.js) cannot be loaded, caused by the hash? I need to manually refresh the whole page, to apply changes. I've already searched for solutions and tried to apply this tip
optimization: {
runtimeChunk: {
name: 'single',
},
}
However my dev console does not log any HMR output anymore and nothing happens. It seems like HMR has stopped working in my browser. Webpack is running and bundling it correctly!
Any ideas? Thanks so far and apologizes for this wall of text.
The optimization.runtimeChunk option should be true or 'single' and not an object with name:
optimization: {
runtimeChunk: 'single',
},
As the documentation explains this is an alias for:
optimization: {
runtimeChunk: {
name: 'runtime',
},
},
Also, you'll want to include the runtime.js file on the page, however you need to do that for your set up. It should only be served in the dev environment (so for example, if NODE_ENV is "development").
In my case I have production, server-side script files alongside webpack-dev-server, and needed this option enabled so it would correctly serve runtime.js from the manifest.json:
devServer: {
devMiddleware: {
writeToDisk: true,
},
}
So I'm trying to learn Vue.js + webpack and initated a project by following these steps:
f:www\> npm install -g vue-cli
f:www\> vue init webpack-simple my-project
f:www\> cd my-project
f:www\> npm install
f:www\> npm run dev
The default page runs on http://localhost:8080/.
Now, in webpack.config.jsfile I have the following lines:
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'main.js'
},
and in the index.html we find the following line <script src="/dist/main.js"></script>
At this point I thought Webpack was a bit like Gulp in that it compiles src files and puts them in the /dist/ folder.
But Webpack never creates the /dist/ folder.
How can the Vue logo be loaded from <img src="/dist/logo.png?82b9c7a5a3f405032b1db71a25f67021"> when /dist/ folder does not exist?
Why is main.js not created?
webpack.config.js (short version)
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'main.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
};
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map';
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
So after some more googling, I found this turorial that explains the entire webpack-simple setup.
Here is the section regarding the /dist/ folder:
npm run build
Right now we are simply using npm run dev to work with and test out an
installation of the Vue Cli tool. This is great
for testing in the local environment, but what about if you actually
want to publish your application to the web? In this case you will
instead run npm run build. This will build your application for
production and you’ll see a new /dist/ folder which contains the
finished bundle.
So during development, the files are placed in a chached / temp location (not sure where)
Is there a way to prevent in React.js, raw HTML display before the CSS stylesheets are completely loaded. I'm using Webpack, Semantic-UI (react version) and React.js.
Is there an equivalent of ng-cloak (angular) in React ?
Here's the content of my webpack config file :
const webpack = require('webpack')
const ManifestPlugin = require('webpack-manifest-plugin')
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const DEBUG = process.env.NODE_ENV !== 'production'
const plugins = [
new webpack.DefinePlugin({
'process.env.NODE_ENV': `"${process.env.NODE_ENV}"`
})
]
const assetsDir = process.env.ASSETS_DIR
const assetMapFile = process.env.ASSETS_MAP_FILE
const outputFile = DEBUG ? '[name].js' : '[name].[chunkhash].js'
if (!DEBUG) {
plugins.push(new ManifestPlugin({
fileName: assetMapFile
}))
plugins.push(new webpack.optimize.UglifyJsPlugin({ minimize: true }))
}
const config = {
entry: {
bundle: ['babel-polyfill', './src/client/index.jsx']
},
module: {
noParse: [],
loaders: [
{ test: /\.json$/, loader: 'json' },
{ test: /\.css$/, loader: 'style!css' },
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /(node_modules|bower_components)/,
query: {
cacheDirectory: DEBUG
}
},
{test:/.svg$/,loader:'url-loader',query:{mimetype:'image/svg+xml',
name:'/semantic/themes/default/assets/fonts/icons.svg'}},
{test:/.woff$/,loader:'url-loader',query:{mimetype:'application/font-woff',
name:'/semantic/themes/default/assets/fonts/icons.woff'}},
{test:/.woff2$/,loader:'url-loader',query:{mimetype:'application/font-woff2',
name:'/semantic/themes/default/assets/fonts/icons.woff2'}},
{test:/.[ot]tf$/,loader:'url-loader',query:{mimetype:'application/octet-stream',
name:'/semantic/themes/default/assets/fonts/icons.ttf'}},
{test:/.eot$/,loader:'url-loader',query:{mimetype:'application/vnd.ms-fontobject',
name:'/semantic/themes/default/assets/fonts/icons.eot'}},
{ test: /\.png/, loader: "url-loader?limit=100000&minetype=image/png" },
{ test: /\.jpg/, loader: "file-loader" }
]
},
node: {
fs: "empty"
},
resolve: {
alias: {
"semantic-ui" : path.resolve( __dirname, "../semantic/dist/semantic.min.css")
},
extensions: ['', '.js', '.jsx', ".css"]
},
plugins,
output: {
filename: outputFile,
path: DEBUG ? '/' : assetsDir,
publicPath: '/assets/'
}
}
if (DEBUG) {
config.devtool = '#inline-source-map'
} else if (process.env.NODE_ENV === 'production') {
config.devtool = 'source-map'
}
module.exports = config
I got this error when I try to load my css from my component :
Cannot find module '/semantic/dist/semantic.min.css'
and the module exists.
I tried the exact same configuration without Webpack and import from component worked.
This is not the correct setup for a production deploy.
By default, Webpack turns your CSS into Javascript code that injects CSS tags in the page. This allows for hot CSS reloading. It's only appropriate for the development environment, obviously. You should be using this default behavior in dev, and should not be using it in production.
In production, you need to build a separate CSS file and load it normally with a <style> tag in your production HTML code. To tell Webpack to pull that out into a file, use the ExtractTextPlugin, which your code requires but never uses.
You should maintain two Webpack config files, one for development which doesn't extract text (and doesn't minify/uglify, etc), and one for production, which correctly minifies, hashes names, extracts text, etc.
I'm using a Yeoman project template called "aspnetcore-spa", which is an ASP.net core 1 template working in conjunction with major SPA frameworks (Angular2 and React).
I created a project with Angular2.The biolerplate's code works fine and there is no problem. Once I add Sass loader to webpack.config.js and make a reference to the Sass file from any angular file.
In webpack.config.js :
var isDevBuild = process.argv.indexOf('--env.prod') < 0;
var path = require('path');
var webpack = require('webpack');
var nodeExternals = require('webpack-node-externals');
var merge = require('webpack-merge');
var allFilenamesExceptJavaScript = /\.(?!js(\?|$))([^.]+(\?|$))/;
// Configuration in common to both client-side and server-side bundles
var sharedConfig = {
resolve: { extensions: [ '', '.js', '.ts' ] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
loaders: [
{ test: /\.ts$/, include: /ClientApp/, loader: 'ts', query: { silent: true } },
{ test: /\.scss$/,include:/ClientApp/, loaders: ["style", "css", "sass"] },
{ test: /\.html$/,include: /ClientApp/, loader: 'raw' },
{ test: /\.css$/, loader: 'to-string!css' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url', query: { limit: 25000 } }
]
}
};
// Configuration for client-side bundle suitable for running in browsers
var clientBundleOutputDir = './wwwroot/dist';
var clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot-client.ts' },
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
var serverBundleConfig = merge(sharedConfig, {
entry: { 'main-server': './ClientApp/boot-server.ts' },
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map',
externals: [nodeExternals({ whitelist: [allFilenamesExceptJavaScript] })] // Don't bundle .js files from node_modules
});
module.exports = [clientBundleConfig, serverBundleConfig];
In my component :
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-wine',
template: require('./wine.component.html'),
styles: require('./wine.component.scss')
})
export class WineComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
I have already installed npm packages pertinent to sass loader :
npm install node-sass sass-loader --save-dev
I have checked the main-server.js file in wwwroot/dist folder which is the result of webpack bundling, I saw that the .scss file is loaded and they styles are processed correctly. Once I run the app though, shows this exception which is coming from the server side rendering side:
An unhandled exception occurred while processing the request.
Exception: Call to Node module failed with error: ReferenceError: window is not defined at E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:573:31 at E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:568:48 at module.exports (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:590:69) at Object. (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:526:38) at webpack_require (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:20:30) at E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:501:22 at Object.module.exports (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:506:3) at webpack_require (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:20:30) at Object. (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:129:25) at webpack_require (E:\Dev\MyApp\MyAppCore\src\MyApp.Web\ClientApp\dist\main-server.js:20:30)
It's obviously because of the webpack's server-side rendering, as it's running the code on Node.js side (through ASP.net Core's Javascript Services) and there is a code that is coupled with the DOM window object which is not valid on node.
Any clues?
I managed to fix the problem, here's the web.config.js bit:
(Notice the loaders for .scss files)
module: {
loaders: [
{ test: /\.ts$/, include: /ClientApp/, loader: 'ts', query: { silent: true } },
{ test: /\.scss$/,include:/ClientApp/, loaders: ["to-string", "css", "sass"] },
{ test: /\.html$/,include: /ClientApp/, loader: 'raw' },
{ test: /\.css$/, loader: 'to-string!css' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url', query: { limit: 25000 } }
]
}
And in the Angular component I changed the styles to this :
(Passed an array of required css files rather than a single css file)
#Component({
selector: 'app-wine',
template: require('./wine.component.html'),
styles: [require('./wine.component.scss')]
})
I am trying to set up webpack hot reloading with react-hot-loader. It mostly seems to be working. I am using webpack in an existing rails app.
But it isn't hot-reloading. It is simply triggering a reload every time my react code is changed. The error messages I get are:
[HMR] Cannot apply update. Need to do a full reload! - dev-server.js:18
[HMR] Error: Aborted because 0 is not accepted - dev-server.js:19
at hotApply (http://localhost:8080/assets/webpack/bundle.js?body=1:380:31)
at hotUpdateDownloaded (http://localhost:8080/assets/webpack/bundle.js?body=1:293:13)
at hotAddUpdateChunk (http://localhost:8080/assets/webpack/bundle.js?body=1:273:13)
at webpackHotUpdateCallback (http://localhost:8080/assets/webpack/bundle.js?body=1:5:12)
at http://localhost:8080/assets/webpack0.bd89931b2fa8e2901794.hot-update.js:1:1
Navigated to http://lvh.me:3000/react_page
Here is my webpack.hot.config.js settings:
var path = require('path');
var webpack = require('webpack');
var config = module.exports = {
// Set 'context' for Rails Asset Pipeline
context: __dirname,
entry: {
App: [
'webpack-dev-server/client?http://localhost:8080/', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./app/frontend/javascripts/app.js' // Your appʼs entry point
],
vendor: ['jquery', 'react', 'react-dom', 'react-redux', 'redux','redux-thunk']
},
devtool: 'inline-source-map',
// Require the webpack and react-hot-loader plugins
plugins: [
//new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.CommonsChunkPlugin(
{
name: 'vendor',
chunks: [''],
filename: 'vendor.js',
minChunks: Infinity
}),
new webpack.NoErrorsPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jquery': 'jquery'
})
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: [
'react-hot',
'babel?presets[]=es2015&presets[]=react'
],
cacheDirectory: true
}
]
},
output: {
path: path.join(__dirname, 'app', 'assets', 'javascripts', 'webpack'), // Save to Rails Asset Pipeline
filename: 'bundle.js', // Will output App_wp_bundle.js
publicPath: 'http://localhost:8080/assets/webpack',
//publicPath: 'http://localhost:8080/assets/webpack' // Required for webpack-dev-server
},
resolve: {
extensions: ['', '.js', '.jsx'],
modulesDirectories: ['node_modules'],
},
};
And I run the code with
webpack-dev-server -d --config webpack.hot.config.js --hot --inline
The rails development environment serves the webpack files outside the application asset pipeline via the webpack-dev-server because of the following setting in my development.rb file.
config.action_controller.asset_host = Proc.new { |source|
if source =~ /webpack\/bundle\.js$/i
"http://localhost:8080"
end
}
I have been trying to get this working for hours. Any help would be appreciated.
Thanks guys!
Ok i was getting the same error, but after trying some things out i figured this out: My root component was a stateless functional component (pure function). I refactored it to a class component and BAM! the hot reloading is working again.
Before:
const App = (props) => (
<div>
<Header links={headerLinks} logoSrc={logoSrc} />
{props.children}
</div>
);
After:
class App extends React.Component {
render() {
return (
<div>
<Header links={headerLinks} logoSrc={logoSrc} />
{this.props.children}
</div>
);
}
}
As the answers provided above are still not working on my side with webpack 5,
Here is the working config from webpack
In webpack.config.js
devServer: {
.
.
.
hot: true,
}
In the webpack entrypoint index.js add
if (module.hot) {
module.hot.accept();
}
In package.json start script
"scripts": {
.
.
"start": "webpack serve --config /webpack.config.js"
},
I recently ran into this exact issue, the fix for me was removing this from the entries array: 'webpack-dev-server/client?http://localhost:9000/',.
As I was also running --hot as a command line argument, there were two instances of webpack-dev-server getting into a bad state.
I don't know if this will specifically help your issue, but I encountered this error recently as well - i fixed it by adding a .js extension to the module I was trying to set up with hmr - here was my code
if (module.hot) {
module.hot.accept('app/Routes', () => (
getRoutes = require('app/Routes')
))
}
I updated it to getRoutes = require('app/Routes.js') and the error disappeared, using webpack ^2.0.0-beta.
it also works if i add the JS extension as the first argument of hot accept like so:
if (module.hot) {
module.hot.accept('app/Routes.js', () => (
getRoutes = require('app/Routes')
))
}
so now it matches whats on the webpack HMR page
I ran into a similar problem.
After 2 days of research and trying different things, I found out the simplest cause to my problem ever:
in webpack.config.js, I had a HRM dev server enabled. And I also had a HMR server run from command line. Thanks to hint from Tyler Kelley (see above), just by removing --hot from command line, it works OK now.
current webpack.config.js
devtool: "inline-source-map",
devServer: {
publicPath: '/dist/',
contentBase: path.join(__dirname, 'public'),
port: 9000,
hot: true
},
With this configuration, don't do this:
npx webpack-dev-server --hot --inline
Do this:
npx webpack-dev-server
For "webpack": "^5.74.0" and "webpack-dev-server": "^4.11.1".
I set devServer.static = ['./webpack-dev-server', './dist'], in webpack.config.js.
There is my config:
module.exports = {
devtool: 'inline-source-map',
devServer: {
open: true,
static: ['./webpack-dev-server', './dist']
},
entry: path.join(__dirname, 'src', 'index.ts'),
module: {
rules: [
{
test: /\.(ttf|png|svg|jpg|jpeg)$/i,
type: 'asset/resource',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
configFile: path.join(__dirname, 'tsconfig.json')
}
}
]
},
mode: 'development',
output: {
filename: '[name][contenthash].js',
path: path.join(__dirname, 'dist'),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'),
inject: 'body'
})
],
resolve: {
extensions: ['.js', '.ts']
}
}