Webpack serve does not include exports on var - javascript

I'm working on a project using webpack, I'm trying to use the webpack-dev-serve package to preview my changes. However when I start the server and load the page the object created by webpack does not have the functions on it Uncaught TypeError: test.a is not a function, when I console log the object webpack creates I can see its an empty object Object { }. Using the exact same webpack config to build the package and including it on my page works fine.
Here is my webpack.config:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
entry: "./src/index.js",
target: "web",
output: {
filename: "test.js",
library: {
name: "test",
type: "var"
}
},
module: {
rules: [{
exclude: /node_modules/
}]
},
resolve: {
symlinks: false
},
plugins: [
new HtmlWebpackPlugin({
title: "Development",
template: "./src/index.html",
scriptLoading: "blocking",
inject: "head"
})
]
};
My index.js is very simple:
export function a(){
console.log("A has been called");
}
My index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<script>
console.log(test);
test.a();
</script>
</body>
</html>

I found a fix from the problem here:
WebPack output.library.type var is undefined
After adding injectClient: false to devServer, and removing scriptloading and inject from the HtmlWebpackPlugin config, webpack serve now works as expects.

Related

Html-webpack-plugin URIError: Failed to decode param '/%3C%=%20htmlWebpackPlugin.files.css%20%%3E'

I ran into a problem from the title. Initially, I only had index.html and everything was going great.
index.html
<!DOCTYPE html>
<html lang="ru" data-base="/"><!-- data-base="//assets.htmlacademy.ru/scripts/demos/"-->
<head>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css %>">
</head>
<body>
<div class="layout loader" id="root"></div>
<script
id="init"
src="main.min.js"
></script>
</body>
</html>
and webpack.config.js
module.exports = () => {
const isProd = process.argv.includes("production");
const mode = isProd ? "production" : "development";
return {
mode,
entry: {
main: './src/main.tsx',
},
output: {
path: resolve(__dirname, 'dist'),
filename: '[name].min.js',
chunkFilename: '[name].bundle.js?hash=[contenthash]',
},
module: {
...
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: false,
files: {
js: 'main.js',
css: 'main.css',
},
cache: false,
}),
...
],
devServer: {
historyApiFallback: true,
host: `0.0.0.0`,
port: process.env.PORT || 8080,
static: resolve('public'),
},
};
};
After that I created a new entry point new-index.html, similar like index.html, but new id. And new webpack config with changes only in html-webpack-plugin:
new HtmlWebpackPlugin({
template: 'public/new-index.html',
filename: 'new-index.html',
inject: false,
files: {
js: 'main.js',
css: 'main.css',
},
cache: false,
}),
At the end package.json scripts:
"start": "webpack serve --mode development",
"start:new-engine": "webpack serve --mode development --config=webpack.new-engine.js",
When I run npm start everything remains as before.
When I run npm run start:new-engine I get this error:
URIError: Failed to decode param '/%3C%=%20htmlWebpackPlugin.files.css%20%%3E'
at decodeURIComponent (<anonymous>)
And my styles isn't processed
DOM screen here
I updated webpack-dev-server and html-webpack-plugin to the latest. Trying run on 14.20 and 16.13 node.
What I'm doing wrong? Thx for ur time.

Webpack to only inject variables into HTML

I am using a basic example of the HtmlWebpackPlugin to inject variables into my HTML page. I do not have an index.js and do not want the bundle.js. How can I exclude the dist bundle.js and only output the updated HTML?
webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
title: 'HTML Webpack Plugin',
bar: 'bar'
})
]
};
index.html (the template):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><%= JSON.stringify(htmlWebpackPlugin.options.title) %></title>
<script><script src="<%=htmlWebpackPlugin.options.favWord%>/socket.io.js"></script></script>
</head>
<body>
<h1>Hello, Webpack!</h1>
<p> My favorite word is <%= JSON.stringify(htmlWebpackPlugin.options.bar) %> </p>
</body>
</html>
The HTML page is generated perfectly, just I do not want the bundle.js generated.
Old question, but for anyone else with the same issue, you can set the inject option to false.
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
title: 'HTML Webpack Plugin',
bar: 'bar',
inject: false,
}),
];

Polymer 3 in other project (like ASP.NET MVC) - create reusable components (PolymerElements)

I am trying to create and reuse Polymer 3 components in ASP.NET MVC application. Right now I am not sure if I am approaching the issue correctly.
So first thing, I want to run everything from IIS express.
Right now I have this issue:
Uncaught TypeError: Failed to resolve module specifier "#polymer/polymer/polymer-element.js".
Relative references must start with "/", "./", or "../".
Here is my code:
Index.cshtml:
<head>
<script src="~/Scripts/PolymerApp/node_modules/#("#webcomponents")/webcomponentsjs/webco
mponents-loader.js"></script>
<script type="module" src="~/Scripts/PolymerApp/first-element.js">
</script>
</head>
<h2>Index</h2>
<div>
<first-element></first-element>
</div>
This is my first-element.js:
import {html, PolymerElement} from '#polymer/polymer/polymer-element.js';
class FirstElement extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
}
</style>
<h2>Hello [[prop1]]!</h2>
`;
}
static get properties() {
return {
prop1: {
type: String,
value: 'first-element',
},
};
}
}
window.customElements.define('first-element', FirstElement);
I created this through cmd: polymer init and then chose element template.
When I run this through polymer serve on polymer`s localhost it works, so i guess there is some build process going on.
Thanks in advance. I hope that i described everything.
I've attempted to do a string replacement in the polymer generated html file using webpack and a plug-in, but it doesn't seem to find the file. Maybe someone more knowledgeable in Webpack-fu can figure out the rest.
// webpack.config.js
var webpack = require('webpack');
const ReplaceInFileWebpackPlugin = require('replace-in-file-webpack-plugin');
"use strict";
module.exports = {
entry: {
main: '/'
},
output: {
filename: "./wwwroot/dist/[name].bundle.js",
publicPath: "/temp/"
},
devServer: {
contentBase: ".",
host: "localhost",
port: 9000
}, mode: "development",
plugins: [
new ReplaceInFileWebpackPlugin([{
dir: './path/to/polymer-built-app/build/default/',
test: /\.html$/,
rules: [{
search: '/#webcomponents/',
replace: '/#{\'#webcomponents\'}/'
}]
}])
]
};
**EDIT: 08/04/2018 **
I've figured this much out:
/// <binding BeforeBuild='Run - Development' />
// webpack.config.js
var webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackStringReplacePlugin = require('html-webpack-string-replace-plugin');
"use strict";
module.exports = {
entry: {
main: './'
},
output: {
publicPath: '/',
path: path.resolve(__dirname, 'wwwroot'),
filename: "./dist/[name].bundle.js"
},
devServer: {
contentBase: ".",
host: "localhost",
port: 9000
},
mode: "development",
plugins: [
new HtmlWebpackPlugin({
"template": "./path/to/index.html",
"filename": "../path/to/Views/Shared/_PolymerLayout.cshtml"
}),
new HtmlWebpackStringReplacePlugin({
'#webcomponents':
'#Html.Raw("#webcomponents")',
'%40webcomponents':
'#Html.Raw("#webcomponents")',
'%40polymer':
'#Html.Raw("#polymer")',
'/node_modules/':
'/path/to/node_modules/',
'./src/path/to/polymer-app',
'<!-- See google short url -->':
'<!-- See google short url -->\r\n<base href="/custom/base/ref">'
})
]
};
If the .js import path starts like this:
from '#polymer/...'
Polymer 3 has a command "polymer build" that automatically translates the path to a real location:
Before:
from '#polymer/polymer/polymer-element.js';
After:
from "./node_modules/#polymer/polymer/polymer-element.js";
You can type ./node_modules/ in front to skip using the polymer build command line tool.

How to load web components in webpack project?

I have started experimenting with webpack and webcomponents. So far I managed only to run this basic web component example without webpack. If I simply load the web component in the index.html using a <script> tag than I get it's content rendered. However, when I try to run the same example using a basic webpack setup I don't see the rendered template.
The server is launched successfully and I can see the console init message. What is the missing step? I would expect to be able to concatenate them this way.
I have the following files:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<base href="/">
<meta charset="UTF-8">
<title>Web Components App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<vs-app></vs-app>
</body>
</html>
main.ts
module.hot && module.hot.accept();
// Components
import { App } from './app';
// Styles
require('./shared/scss/main.scss');
console.log('Initialise Main');
app.ts
/**
* App
*/
export class App extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = this.template;
}
get template() {
return `
<div>This is a div</div>
`;
}
}
window.customElements.define('vs-app', App);
webpack-common.js
const webpack = require("webpack"),
path = require("path"),
CopyWebpackPlugin = require('copy-webpack-plugin'),
HtmlWebpackPlugin = require('html-webpack-plugin'),
ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
// Constants
const BUILD_DIR = path.join(__dirname, "../../build"),
PUBLIC_DIR = path.join(__dirname, "../../public"),
NODE_MODULES_DIR = path.join(__dirname, "../../node_modules");
// Shared between prod and dev
module.exports = {
entry: "./public/main.ts",
output: {
// Since webpack-dev-middleware handles the files in memory, path property is used only in production.
path: BUILD_DIR,
publicPath: "/",
filename: "bundle.js"
},
resolve: {
extensions: ["*", ".ts", ".js"]
},
module: {
loaders: [{
test: /\.ts?$/,
loader: "awesome-typescript-loader",
include: PUBLIC_DIR,
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
loader: "style-loader!css-loader!autoprefixer-loader"
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader'
},
]
},
// Base plugins
plugins: [
new CopyWebpackPlugin([
{
from: `public/shared/images`,
to: 'images'
},
]),
new HtmlWebpackPlugin({
template: 'public/index.html'
}),
// Load bundle.js after libs are loaded
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'defer'
})
],
stats: {
colors: true,
modules: true,
reasons: true,
errorDetails: true
}
};
Edit
Eventually I got the component rendered moving the following line window.customElements.define('vs-app', App); from app.ts to main.ts. In the mean time I discovered that even that is not necessary.
// This is enough to trigger rendering
import { App } from './app';
App;
However, I still have an issue. Because of webpack hot reload, the component ends up registered twice, giving an error. Still looking for a fix.
Edit 2
After some research online I managed to find the problem: I did not have the inject: false property. This triggered webpack to load twice the same stuff. Looks like I can finally move forward with developing the app. However I would love to find out alternative ways to this setup, just to get confirmation that I'm on the right road.
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: false
}),

How to disable or prevent ReactJS from looking for a document when it server side renders?

I am trying to use GSAP within my ReactJS app for animation on the client side. If I install the gsap module via npm and then try to use gsap within my modules, I get the following error:
node_modules/gsap/src/uncompressed/TweenMax.js:2535
_doc = document,
^
ReferenceError: document is not defined
at Function.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:2535:11)
at [object Object].check (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5794:61)
at new Definition (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5811:10)
at window._gsDefine (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:5816:12)
at Array.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:2489:11)
at /Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:7570:9
at Object.<anonymous> (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/gsap/src/uncompressed/TweenMax.js:7581:3)
at Module._compile (module.js:435:26)
at Module._extensions..js (module.js:442:10)
at Object.require.extensions.(anonymous function) [as .js] (/Users/gcardella/Documents/TOG/SOLID/mockups/solid-website/node_modules/babel-register/lib/node.js:138:7)
Is there a way in ReactJS to code: If it renders on the server, there's no document so don't load gsap, but once the compiled bundle.js (my client side react js that takes over the client) is downloaded, use gsap because the document exists?
The work around I'm currently using is to embed gsap in the index.ejs:
<!DOCTYPE html>
<html>
<head>
<title>Solid Website</title>
</head>
<body>
<section id="react-app" class="container-fluid">
<%- markup %>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TimelineMax.min.js"></script>
<script src="build.js"></script>
</body>
</html>
Update: the webpack.config.js
var path = require('path');
module.exports = {
entry: path.join(process.cwd(), 'client-render.js'),
output: {
path: './public/',
filename: 'build.js'
},
module: {
loaders: [
{
loader: 'babel'
}
]
}
}
In my webpack.config.js:
module.exports = {
entry: path.join(process.cwd(), 'client/client-render.js'),
output: {
path: './public/',
filename: 'build.js'
},
module: {
loaders: [
{
test: /.js$/,
loader: 'babel'
}
]
},
/* this is new */
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
APP_ENV: JSON.stringify('browser')
}
})
]
}
Then in my modules:
if (process.env.APP_ENV === 'browser') {
load_the_module_for_browser;
}
Try adding web as your target in your config. https://webpack.github.io/docs/configuration.html#target it's supposed to be the default though.
var path = require('path');
module.exports = {
entry: path.join(process.cwd(), 'client-render.js'),
output: {
path: './public/',
filename: 'build.js'
},
module: {
loaders: [
{
loader: 'babel'
}
]
},
target: "web",
}
inject the process.env in the plugin property of the webpackConfig like that:
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(isDevelopment ? 'development' : 'production'),
IS_BROWSER: true
}
})
]

Categories