How to export bundled libraries in my vendor.js (CommonsChunkPlugin)? - javascript

I have two webpack 2 projects
The 1st one, let's call it lib1 is a library of reusable React components. In the webpack config it is exported as a library with the name lib1. The project lists react and react-dom as external dependencies.
The 2nd one, let's call it proj1 is an app that uses lib1. Because lib1 is served on a cdn, it's listed as an external dependency. The project also depends on react and react-dom. Using CommonsChunkPlugin I generare a vendor.js that includes react and react-dom (and eventually other dependencies).
When I run proj1 in the browser, the code inside lib1 fails because it can't find react. The libraries are loaded in this order:
<script src="dist/vendor.js"></script>
<script src="http://cdn.com/lib1/lib1.js"></script>
<script src="dist/bundle.js"></script>
I guess the issue is that react and react-dom are not exported by my vendor.js file.
I tried using the library option like this (int proj1):
library: "[name]",
libraryTarget: "umd"
But it creates window.vendor not window.React and window.ReactDOM.
How do I do that?
lib1 config
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, "dist"), // string
filename: "bundle.js",
publicPath: "/dist/",
library: "lib1",
libraryTarget: "umd",
},
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, "node_modules"),
}]
},
externals: ["react", "react-dom"],
};
proj1 config
var webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
bundle : './src/index.js',
vendor : ['react', 'react-dom']
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
publicPath: "/dist/",
library: "[name]",
libraryTarget: "umd",
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
})
],
module: {
rules: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: path.resolve(__dirname, "node_modules"),
}]
},
externals: ["lib1"],
devtool: "source-map"
};

Related

Disable Strict Mode in None Module Library

I want to bundle a JavaScript project by WebPack but there is more problems in none-module libraries because imported them by 'import' capability,ECMAScript 6 module loader run strict mode by default and it tack more errors.
Question :
How can I import none module libraries without strict mode to bundle them by WebPack?
index.js
import '../examples/js/libs/draco/draco_encoder.js';
import './js/libs/codemirror/codemirror.js';
import './js/libs/codemirror/mode/javascript.js';
import './js/libs/codemirror/mode/glsl.js';
...
webpack.config.js
const path = require('path');
const webpack = require('webpack');
// webpack.config.js
module.exports = {
entry: {
polyfills: './editor/polyfills',
index: './lib/index.js',
},
mode: 'development',
output: {
path: __dirname,
publicPath: '/',
filename: './editor/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
watchContentBase: true,
publicPath: "/",
contentBase: "./",
hot: true,
port: 8080,
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
};
babel.config.json
{
"presets": [
"#babel/preset-env"
]
}
I tryed :
babel
esmify
browserify
Shimming in WebPack
...
Thanks for your attention.
Webpack enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript.
About loaders: Loaders.
You can easily write your own loaders using Node.js : Writing Loader.
For execute JS script once in global context that can solved my problem : Script Loader

Webpack can't resolve relative path import express static

I'm working on an outlook addin I have an express server running. I am setting webpack because I need to transpile js to es5 to make it work in Outlook Desktop. Here is the simplified project structure.
/public
/javascripts
ssoAuth.js
/addin
/commmands
commands.js
commands.html
/server
/bin
/helpers
app.js
The public folder is set as a static folder in my express server
app.use(express.static(path.join(__dirname, '../public'),
My problem is in commands.js I import ssoAuth.js with es6 module import with relative path :
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
It works fine when I run node ./server/app.js and load my outlook addin, but when I want to use Webpack to bundle, the import is not working, I get :
ERROR in ./addin/commands/commands.js
Module not found: Error: Can't resolve '/javascripts/ssoAuth.js'
I can't figure out how to configure webpack to allow the imports from the public folder.
Here are my webpack config files :
webpack.config.js :
const config = {
devtool: "source-map",
entry: {
polyfill: "#babel/polyfill",
commands: "./addin/commands/commands.js"
},
resolve: {
extensions: [".ts", ".tsx", ".html", ".js"]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.html$/,
exclude: /node_modules/,
use: "html-loader"
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: "commands.html",
template: "./addin/commands/commands.html",
chunks: ["polyfill", "commands"]
})
]};
webpack.server.config.js :
return ({
entry: {
server: './server/bin/www',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new CopyWebpackPlugin([
{
to: "./public",
from: "./public"
}
])
]})
Can you help figure this out ? Is there a better folder structure that I should use to make it work ?
Thanks
You're using an absolute path
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
// ^ this will look in your topmost directory on your OS
The relative path, from commands.js, would be:
import getGraphAccessToken from "../../javascripts/ssoAuthES6.js";
Alternatively, you can set Webpack to look for modules from your root directory by adding the following to your webpack configuration:
{
// ...
resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
// ...
}
Then you can import from your project's root directory from anywhere, like so:
import getGraphAccessToken from "javascripts/ssoAuthES6.js";
Some other points:
Since you're setting the extensions: [".ts", ".tsx", ".html", ".js"], you don't need to provide file extensions for those imports
You specify .ts and .tsx in your webpack config, but you are using .js files. Consider removing the Typescript extensions
If you are using Typescript, you will need to update import paths in your tsconfig.json
You can consider import path aliases in both Webpack and Typescript to be more explicit that your imports are coming from your project root. Instructions here

webpack-dev-server not recompiling the output file

This is my webpack file, nothing special
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'public/scripts'),
publicPath: '/public/scripts/',
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}]
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
watchContentBase : true,
publicPath: '/scripts/'
}
}
However, when I run 'npm run webpack-dev-server', I get the normal node.js output but the website does not update when new changes are made. I deleted the bundle.js file and when I ran it again, I got an error saying 'bundle.js cannot be found'. I figured out that bundle.js is not being recompiled at all when running this command.
I am on windows if that makes any difference. Any help would be appreciated.
EDIT: Below is my folder structure.
You need to use watchContentBase option for devServer:
watchContentBase:true
Would also recommend setting hot:true for modules replecement and open:true - so when you will run the dev server it will automatically open you your site at default browser.
More on devServer options you could find here - https://webpack.js.org/configuration/dev-server/#devserverwatchoptions-
EDIT
So after quite long conversation in chat, here are the results:
Still to "live-reload" the page you should use watchContentBase
But there were other issues in this case - publicPath in devServer and outputPath were not the same and then index.html should reference bundle.js under /public/scripts
New webpack.config.js:
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '/public/scripts'),
publicPath: '/public/scripts',
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}]
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
watchContentBase : true,
publicPath: '/public/scripts'
}
}
New src for bundle in Index.html:
/public/scripts/bundle.js

How to exclude directory from getting bundled by Webpack?

Expected:
When I build with webpack, all my JS files get bundled except for the files in the ./src/Portfolio directory as per my Webpack.config.js settings.
Actual:
Webpack bundles all the files including the ones in the directory despite the settings and other variations i have provided within webpack.config.js.
Code:
Webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: [
path.resolve(__dirname, './src/Portfolio/')
]
}
]
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
Output:
How can i successfully exclude the ./src/Portfolio directory and its
contents?
Depending on what your folder structure looks like it appears you aren't providing it the right directory location to exclude. I would think something like this should work, but if not please share your folder structure.
const path = require('path');
module.exports = {
entry: './src/index.js',
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: [
'./src/Portfolio/'
]
}
]
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
I know the op is using javascript, fyi a similar problem can occur using typescript with webpack.
In this case excluded directories can be added to tsconfig.json instead of webpack.config.js,
//tsconfig.json
{
"compilerOptions": {
...
},
"exclude": [
"./src/Portfolio/",
]
}

How to customize webpack build script for React App

I am moving a web app to react, therefore and moving from Grunt as a buildtool over to webpack. Right now, the below code is the webpack.config file. This is set up as recommended for developing and then has a build script (npm run and npm build)
However, the build script now only concatenates the components/react js files and puts them at the root of the dist folder. No other files are copied over. I don't understand the point of the build script if that's all it does. But I need to be able to add that in, however, no resource with reacts build scripts shows how you would go about that
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./app/src/components/app.js",
output: {
path: path.join(__dirname, "/dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./app/index.html"
})
]
};
you do not need a '/'
output: {
path: path.join(__dirname, "dist"),
filename: "index_bundle.js"
},

Categories