I try to implement hot reloading in a laravel app. But I have problem doing output using webpack. When I do http://localhost/bundle.js it's 404 not found. I wonder why. In my terminal I did see bundle.js is bundled by webpack, but where has it gone to?
gulpfile.js
var elixir = require('laravel-elixir');
var webpackDevMiddleware = require('webpack-dev-middleware');
var webpackHotMiddleware = require('webpack-hot-middleware');
var webpackConfig = require('./webpack.dev.config');
var bundler = webpack(webpackConfig);
gulp.task('hot', function(){
elixir(function(mix) {
browserSync({
proxy: 'somewhere.local',
middleware: [
webpackDevMiddleware(bundler, {
publicPath: '/'
}),
webpackHotMiddleware(bundler)
]
});
});
});
webpack.dev.config.js The problem is here
module.exports = {
debug: true,
context: path.join(__dirname, 'resources/assets/bundle/entries'),
entry: ['./feed.js'],
output: {
path : path.join(__dirname, 'public/bundle'),
publicPath : '/',
filename : 'bundle.js'
}
resolve: {
extensions: ['', '.js', '.jsx']
}
}
my laravel view
I also included
<script src="http://localhost:3000/bundle.js"></script>
Something is wrong in my webpack config file. Here's my site directory :
webpack dev server doesn't write the bundle to disk.
This modified bundle is served from memory at the relative path specified in publicPath (see API). It will not be written to your configured output directory. Where a bundle already exists at the same URL path, the bundle in memory takes precedence (by default).
you can find out more here: https://webpack.github.io/docs/webpack-dev-server.html
depending on your exact needs, you might consider using a different webpack configuration
Related
I have a Vue.js project that is working fine in localhost.
But when I build and deploy to production, I need the static files (.css and .js) to be served on a "static" subdomain.
For example, my main URL:
https://www.example.com/index.html
The static assets will be:
https://static.example.com/css/app.50f83e17.css
https://static.example.com/js/chunk-vendors.6f495bf3.js
When I run "npm run build" Webpack build the "index.html" file loading like this:
<link href=/css/app.50f83e17.css rel=stylesheet>
But I need the href to be like this:
<link href=https://static.example.com/css/app.50f83e17.css rel=stylesheet>
How do I configure Vue.js or Webpack to build the "index.html" using a different subdomain for the CSS and JS?
To achieve this you would need to use webpack publicPath
You can configure webpack to build index.html using a different subdomain,
webpack.config.js
import webpack from 'webpack';
export default {
output: {
..
publicPath: 'https://static.example.com/js/',
},
};
npm run build Webpack build the "index.html" would have
..
..
<script type="text/javascript" src="https://static.example.com/js/chunk-vendors.6f495bf3.js"></script>
For css,
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: 'https://static.example.com/css/',
},
},
'css-loader',
],
},
],
},
};
You can also specify publicPath at runtime,
entry.js
__webpack_public_path__ = myRuntimePublicPath;
// rest of your application entry
Note: please consider adding a environment variable instead of hardcoding the asset CDN path, and pass the environment variable via npm scripts, alternately you can also define a global publicPath
var myRuntimePublicPath = 'https://static.example.com/js/'
and use it in the entry file (say entry.js) as displayed above.
refer: webpack publicPath and mini-css-extract-plugin publicPath
In case of using Vue Router
The base URL your application bundle will be deployed at publicPath (known as baseUrl before Vue CLI 3.3).
vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? 'https://static.example.com/js/'
: '/'
}
Vue Router
// override the base to hardcoded default value as it gets the value from publicPath
base: '/'
This will allow subdomain for javaScript bundle of vuejs build.
I am currently working on a library which should dynamically load a JavaScript from a remote host and instantiate that.
I am writing the library in TypeScript and my plan is to use Webpack as a bundler.
On another host (remote system) runs a provider which should serve JavaScript code (see here: https://stubs.d-koppenhagen.de/stubs/SimpleStub.js).
The library will dynamically resolve "Identitys" via Webfinger. These Identitys represented by an object and they having a property pointing to a "Stub Provider" which will serve JavaScript code (the link I mentioned before). My library should load this script during runtime (s the library don't know the target for this stubs before) and should use it.
currently my webpack.config.js looks like the following:
var path = require('path');
var webpack = require('webpack');
var WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PATHS = {
src: path.join(__dirname, './src'),
build: path.join(__dirname, './dist')
};
module.exports = {
entry: {
wonder: PATHS.src + '/wonder'
},
output: {
path: PATHS.build,
filename: '[name].js',
library: 'Wonder',
libraryTarget: 'umd'
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
},
resolve: {
extensions: ['.ts', '.js']
},
plugins: [
new WebpackBuildNotifierPlugin()
]
};
And here is a part of the library code:
require.ensure([], function() {
require(localMsgStubUrl);
});
When I am now including the bundled library in an example app, I will get the following error:
Error: loading chunk failed
So is there a way to tell webpack not to bundle the code which is required from a external resource loaded from a URL so that I can use that code like it is?
I don't want to tell webpack the URL statically in a config as maybe other stubs I am loading are located on a different target.
Thanks in advance for your help!
I was installing a react startup app and added Webpack, but it says Can't resolve './src/index.js'.
Browser Shows
My Files Path and Package.json Contents
Webpack.config.js Contents
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: path.join(__dirname, "public"),
devtool: debug ? "inline-sourcemap" : false,
entry: "./src/index.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2016', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
}
]
},
output: {
path: __dirname + "/public/",
filename: "build.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
Your base URL is path.join(__dirname, "public"), and your entry is ./src/index.js. Webpack tries to find ./src/index.js in public dir; obviously it does not exist. You should modify entry to ../src/index.js.
The other way I find out to fix this problem is to use path.resolve().
const path = require('path');
module.exports = {
mode: "production",
entry: path.resolve(__dirname, 'src') + 'path/to/your/file.js',
output: {
/*Webpack producing results*/
path: path.resolve(__dirname, "../src/dist"),
filename: "app-bundle.js"
}
}
This will make sure, webpack is looking for entry point in src directory.
By the way it's the default entry point. You can also change this entry point to your suitable location. Just replace the src directory with the other directory you want to use.
My webpack.config.js was named Webpack.config.js and the new cli was looking for something case-sensitive.
Webpack does not look for .js files by default. You can configure resolve.extensions to look for .ts. Don't forget to add the default values as well, otherwise most modules will break because they rely on the fact that the .js extension is automatically used.
resolve: {
extensions: ['.js', '.json']
}
The entry path is relative to the context. It's looking for a file in public/src/ when you want it to look for a path in just /src. Looking at the rest of your webpack.config.js it doesn't seem like you need the context line at all.
https://webpack.js.org/configuration/entry-context/
I had the same problem and found that it was caused by having installed create-react-app globally in the past using npm install -g create-react-app.
As create-react-app should now not be installed globally, I needed to uninstall it first using npm uninstall -g create-react-app and then install it in my project directory with npx create-react-app *my-app-name*.
My solution was to put App.js file on a components folder inside the src folder and keep the inde.js just inside the src one
I had same problem. And solutions was really 'at the top' I forgot to add module.exports inside my webpack.prod.js.
So instead of
merge(common, {
...
});
use
module.exports = merge(common, {
...
});
Electron 1.6.5, Webpack 2.4.1
I'm using electron-react-boilerplate with a webview component. I inject a preload script into the webview that does something like this:
const { ipcRenderer } = require('electron');
const doSomething = require('./utils/do-some-thing.js');
document.addEventListener('DOMContentLoaded', event => {
doSomeThing()
// tell scraper to get started
ipcRenderer.sendToHost('THING IS DONE', [{ url: document.URL }]);
});
webview needs this script passed as a file:// path like so:
<webview
preload={'./some/folder/preload.js''}
{...props}
/>
The problem is that my webpack setup doesn't transpile preload.js because it isn't explicitly called via require(). Then, when I build the app, the path ./some/folder/ doesn't exist.
I've tried setting webpack to create a second compiled script like so:
entry: [
'babel-polyfill',
'./app/index',
'./some/folder/preload.js'
],
output: {
path: path.join(__dirname, 'app/dist'),
publicPath: '../dist/'
},
But this leads to a JavaScript heap out of memory error, which leads me to believe this isn't correct.
Also: wouldn't this approach duplicate electron in the ./dist folder since it's require()'d by both preload.js and index.js ?
You could use the electron-main and electron-preload configurations of webpack:
const path = require('path');
module.exports = [
{
entry: './src/index.js',
target: 'electron-main',
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.bundled.js'
},
node: {
__dirname: false,
}
},
{
entry: './src/preload.js',
target: 'electron-preload',
output: {
path: path.join(__dirname, 'dist'),
filename: 'preload.bundled.js'
}
},
]
You get two bundles after building, but Electron is not in either of them, so no duplicates.
Notice the __dirname: false, which is required since otherwise webpack replaces __dirname always replaced by / by webpack, leading to an unexpected behaviour in almost all cases (see here for further information, should be false by default, but wasn't for me).
We had a similar issue where we had several preload scripts instead of one. Our solution was to use the CopyPlugin. So for us, the config looks like this:
const CopyPlugin = require("copy-webpack-plugin");
plugins.push(new CopyPlugin([{ from: "src/container-with-scripts/", to: "preloadScripts/" }]));
module.exports = {
module: { rules }, // imported from elsewhere
target: "electron-renderer",
node: { global: true },
plugins,
resolve: {
extensions: [".js", ".ts", ".jsx", ".tsx", ".css", ".scss"]
}
};
So we just take the folder containing all our scripts and copy them to the autogenerated .webpack folder.
I was having the same problem and here's solution that worked for me:
Electron-webpack documentation now contains example how to add additional entries.
"electronWebpack": {
"main": {
"extraEntries": ["#/preload.js"]
}
}
Note that you can use the # alias to reference your main.sourceDirectory
in this case it's path to your main process script which will be src/main by default
This adds preload script from src/main/preload.js into webpack entries.
Then you need to add preload script into window with
new BrowserWindow({
webPreferences: {
nodeIntegration: true,
preload: path.resolve(path.join(__dirname, "preload.js")),
}
})
That's all. __dirname was giving me relative path and electron requires absolute path for preload script so it was failing. path.resolve will get you absolute path needed to make it work.
Electron provides an option to load a script before any other execution in your DOM.
You have to provide your pre-load script file path while creating a browser window and file path of the script should be the absolute.
You can find reference here
I guess I'll start with my webpack config.
const webpack = require('webpack');
const path = require('path');
/**
* Environment
*/
const nodeEnv = process.env.NODE_ENV || 'development';
const isProduction = nodeEnv === 'production';
const isDevelopment = !isProduction;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const sourcePath = path.join(__dirname, 'assets');
const buildPath = path.join(__dirname, 'dist');
const extractSass = new ExtractTextPlugin({
filename: '[name].[contenthash].css',
disable: isDevelopment
});
/**
* Plugins
*/
const plugins = [
new HtmlWebpackPlugin({
template: path.join(sourcePath, 'index.html'),
}),
extractSass
];
if (isProduction) {
} else {
plugins.concat([
new webpack.HotModuleReplacementPlugin(),
]);
}
module.exports = {
entry: ['./assets/app.js', './assets/app.scss'],
devtool: isProduction ? 'eval' : 'source-map',
plugins: plugins,
module: {
rules: [{
test: /\.scss$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}]
},
output: {
filename: 'bundle.js',
path: buildPath
},
devServer: {
contentBase: buildPath,
port: 9000
}
};
This all works fine when running on the webpack dev server but I'm trying to figure out how this fits together on a production environment.
As you can see, as per the sass-loader documentation, I'm creating a file called [name].[contenthash].css if NODE_ENV is set to production. I love the idea of serving files based on the content hash because I love integrity.
The difficulty I'm having is understanding how I can pass that file name, that content hash into the index.html template I'm creating so that I can <link> the stylesheet.
Is it a server side thing?
Is there any way to pass that file name into the HTML template on
production?
Is it intentional that I do it manually or script it out?
I just don't understand how these two components come together to produce a publishable build. HtmlWebpackPlugin produced a .html in the output directory but obviously it has no innate understanding of where to find it's styles.
Your config seems correct.
Is there any way to pass that file name into the HTML template on production?
What should be happening is that the HtmlWebpackPlugin should be creating a new index.html file in your buildPath directory, which has the generated bundles automatically injected in it (for example the generated CSS bundle will be injected in the head tag and the generated script bundles at the bottom of the body tag)
Beyond that it is just a matter of serving that dist/index.html to whoever visits your site/app. So the answer to
Is it a server side thing?
is yes.
Try doing a build without the dev server, by simply running webpack, so you can see the output of your configuration (the dev server builds things in memory, so you do not actually get to see them)