Webpack with requirejs/AMD - javascript

I'm working on a new module for an existing project that still uses requireJS for module loading. I'm trying to use new technologies for my new module like webpack (which allows me to use es6 loaders using es6 imports). It seems like webpack can't reconcile with requireJS syntax. It will say things like: "Module not found: Error: Can't resolve in ".
Problem: Webpack won't bundle files with requireJS/AMD syntax in them.
Question: Is there any way to make webpack play nice with requireJS?
My final output must be in AMD format in order for the project to properly load it. Thanks.

I had the same question and I managed to achieve it. Below is the same webpack.config.js file.
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
let basePath = path.join(__dirname, '/');
let config = {
// Entry, file to be bundled
entry: {
'main': basePath + '/src/main.js',
},
devtool: 'source-map',
output: {
// Output directory
path: basePath + '/dist/',
library: '[name]',
// [hash:6] with add a SHA based on file changes if the env is build
filename: env === EnvEnum.BUILD ? '[name]-[hash:6].min.js' : '[name].min.js',
libraryTarget: 'amd',
umdNamedDefine: true
},
module: {
rules: [{
test: /(\.js)$/,
exclude: /(node_modules|bower_components)/,
use: {
// babel-loader to convert ES6 code to ES5 + amdCleaning requirejs code into simple JS code, taking care of modules to load as desired
loader: 'babel-loader',
options: {
presets: ['es2015'],
plugins: []
}
}
}, { test: /jQuery/, loader: 'expose-loader?$' },
{ test: /application/, loader: 'expose-loader?application' },
{ test: /base64/, loader: 'exports-loader?Base64' }
]
},
resolve: {
alias: {
'jQuery': 'bower_components/jquery/dist/jquery.min',
'application': 'main',
'base64': 'vendor/base64'
},
modules: [
// Files path which will be referenced while bundling
'src/**/*.js',
'src/bower_components',
path.resolve('./src')
],
extensions: ['.js'] // File types
},
plugins: [
]
};
module.exports = config;

Related

Get list of webpack output files and use in another module for PWA

I'm trying to build a progressive web app, with support for offline usage.
According to MDN, the way to make PWAs work offline is to add the required resources to a cache in the service worker. This requires that the service worker code knows each of the output files. Ideally, this shouldn't be harcoded, and should be generated by webpack, since it knows what files it generates.
I'm struggling to actually generate this list. From my search, there are two plugins that can generate a json file containing a list of the files - webpack-assets-manifest and webpack-manifest-plugin. I can use these in combination with separate targets to generate a manifest with the page files. But I can't import the manifest, since webpack doesn't actually write the manifest until everything is done.
How can I import a list of files that one entry point generates and use them in another entry point/module?
webpack.config.js:
const path = require('path');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const frontend = {
mode: "development",
entry: {
page:"./src/page/page.tsx",
},
devtool: 'inline-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.html?$|\.png$/,
type: "asset/resource",
generator: {
filename: "[name][ext]",
},
},
{
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.json$/,
type: "asset/resource",
exclude: /node_modules/,
}
],
},
resolve: {
extensions: [".html", ".tsx", ".ts", ".js"],
},
plugins: [
new WebpackAssetsManifest({
output: "page-files.json",
writeToDisk: true,
}),
]
};
const serviceworker = {
mode: "development",
entry: {
serviceworker: "./src/serviceworker/serviceworker.ts",
},
devtool: 'inline-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.html?$|\.png$/,
type: "asset/resource",
generator: {
filename: "[name][ext]",
},
},
{
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.json$/,
resourceQuery: /link/,
type: "asset/resource",
exclude: /node_modules/,
},
{
test: /\.json$/,
resourceQuery: /str/,
type: "asset/source",
exclude: /node_modules/,
}
],
},
resolve: {
extensions: [".html", ".tsx", ".ts", ".js"],
},
};
module.exports = [frontend, serviceworker];
serviceworker.ts:
import files from "../../dist/page-files.json?str";
console.log(files);
Error is:
Module not found: Error: Can't resolve '../../dist/page-files.json?str' in '<REDACTED>/src/serviceworker'
(When I build it again, it will find the file from the previous build)
Rather than relying on pre-existing webpack plugins to generate assets, I think you're going to need to write your own plugin for this use case. And if you want that plugin to write the manifest to an entry that itself needs to be bundled/compiled, creating a child compilation in that plugin would be the way to do it.
This is unfortunately not a straightforward task, but you can refer to the source code for the workbox-webpack-plugin's InjectManifest plugin, which more or does what you describe, as inspiration.
Alternatively... you can just use InjectManifest directly, if that meets your use case. While it's part of the Workbox family of libraries, InjectManifest will only actually do two things: process the entry file you pass in as swSrc via a child compilation, and replace the symbol self.__WB_MANIFEST anywhere in that swSrc file with an array of {url: '...', revision: '...'} entries generated based on the assets in the main configuration, filtered by any include/exclude parameters.
So if you don't plan on using Workbox, you can just make use of that self.__WB_MANIFEST value from your own code.
// service-worker.ts
const manifest = self.__WB_MANIFEST || [];
self.addEventListener('install', (event) => {
// Your code to cache the contents of manifest goes here.
});
// webpack.config.js
const {InjectManifest} = require('workbox-webpack-plugin');
module.exports = {
// ...other webpack config...
plugins: [
new InjectManifest({
swSrc: 'src/service-worker.ts',
swDest: 'service-worker.js',
// ...exclude/include config here...
}),
],
};
The reason behind this behavior is that webpack runs these 2 configurations parallelly. By forcing webpack to run sequentially we can fix the problem.
To do serial processing, add module.exports.parallelism = 1; at end of your webpack config.
module.exports = [frontend, serviceworker];
module.exports.parallelism = 1;
Here is the documentation from webpack, https://webpack.js.org/configuration/configuration-types/#parallelism

Why can't Webpack resolve ‘babel-loader’?

When I configure Webpack for this code base, Webpack complains that it Can't resolve 'babel-loader'. What exactly is failing, and how can I ask Webpack what its complaint is?
The Webpack configuration:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './source/main.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
},
resolve: {
modules: [
path.resolve(__dirname, 'source'),
'/usr/share/javascript',
'/usr/lib/nodejs',
],
},
module: {
loaders: [
// Transform JSX with React.
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react'],
},
},
],
},
};
The entry module:
// source/main.jsx
"use strict";
import Application from './components/Application';
const applicationElement = <Application />;
ReactDOM.render(
applicationElement,
document.getElementById('application'),
);
Is the problem something like a search path, and if so why can't the error tell me what setting I need to correct?
The babel-loader module is definitely installed. (I therefore don't want to install it again – so npm install won't help – I am trying to tell Webpack to use it from the already-installed location.) Its package definition is at /usr/lib/nodejs/babel-loader/package.json.
I've pointed Webpack's resolver there – instead of its default resolver behaviour – using the resolve.modules list of search paths. Correct?
So the resolver should be able to find it there by the specified search path /usr/lib/nodejs and the name babel-loader, no?
(This raises a separate question, about how to convince Webpack to just tell me what it's looking for so it can be diagnosed more easily.)
How can I tell Webpack the specific location it should use to resolve that babel-loader name?
The Webpack configuration setting resolve is for modules that are imported. The loaders are resolved differently; the resolveLoader setting configures how to resolve the loaders specifically.
So, adding resolveLoader to the Webpack configuration works:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './source/main.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
},
resolve: {
// Configure how Webpack finds modules imported with `import`.
modules: [
path.resolve(__dirname, 'source'),
'/usr/share/javascript',
'/usr/lib/nodejs',
],
},
resolveLoader: {
// Configure how Webpack finds `loader` modules.
modules: [
'/usr/lib/nodejs',
],
},
module: {
loaders: [
// Transform JSX with React.
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react'],
},
},
],
},
};
I think that the webpack.config you're looking for is the following:
module: {
loaders: [
{test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
]
}
Hope helps :)

Bundling node.js web API with webpack

I'm implementing a web API based on node.js. API can interact with a database. So I use node-postgres library for a data access layer.
Now I need to configure webpack in the right manner in order to bundle api in a sigle file. However I can't do that because of node-postgres dependency "pg-native". I can only build api with this code in webpack.config.js:
externals: {
'pg': 'commonjs pg'
}
But this solution force me to keep node_modules folder when I going to deploy the API.
Here is my webpack.config.js:
var path = require('path');
var nodeNativeModules = {};
module.exports = function(environment) {
var entryCfg = '';
switch(environment){
case 'development':
entryCfg = { 'main_ts': './src/api/main.ts'};
break;
}
var CONFIG = {
entry: entryCfg,
target: 'node',
output: {
path: path.join(__dirname, 'dist/'),
filename: '[name].js'
},
resolve: {
extensions: ['.ts', '.js', '.json'],
},
externals: {
'pg': 'commonjs pg'
},
module: {
loaders: [{
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.ts$/,
loaders: [
'awesome-typescript-loader',
],
exclude: [/\.(spec|e2e)\.ts$/]
},]
},
devtool: 'source-map'
}
return CONFIG;
}
Is there a possible way to bundle node-postgres?
How to configure webpack to bundle native module dependencies?
Since I don't use 'pg-native' my issue becomes a webpack configuration issue.
Here is the answer that helps me https://github.com/serverless-heaven/serverless-webpack/issues/78

jshint and sass/scss not working with Webpack 2.2

/Website
---/Scripts/*.js
---/sass/*.scss
---/dist/*.css
I want to do 2 things :
JShint the .js files
Compile the scss file and move them to dist folder
I tried this configuration, but it does't seem to work.
var webpack = require('webpack'),
path = require("path"),
glob = require("glob"),
jshint = require('jshint-loader'),
ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: glob.sync("./Scripts/**/*.js"),
output: {
path: "./Scripts/",
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "jshint-loader"
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}
]
},
resolve: {
extensions: [".js", ".css", ".sass", "scss"]
},
plugins: [
new ExtractTextPlugin('./dist/[name].css')
]
}
When I run webpack, the .js files are bundled into a main.js file and errors are emitted.
What am I missing to be able to JSHint the .js files
Is it possible to tell webpack to not bundle the files and just execute the JSHint
Why Im not getting the css files

Webpack error when importing CSS vendor library into index.js

I am moving existing javascript vendor libraries into a webpack setup, where possible using npm to install an npm module and deleting the old script tag on the individual page as bundle.js and bundle.css include it
In index.js, I have the following
import 'materialize-css/dist/css/materialize.min.css';
However, when webpack is run, it errors with the following
Module parse failed: .......Unexpected character ''
You may need an appropriate loader to handle this file type.
So, for some reason, webpack is looking at the entire materialize folder, rather than just the single minified css file, and is then error when it comes across materialize/fonts directory.
I am unclear why this is happening, and what to do to stop it. Any advice would be greatly appreciated.
My webpack config is below
const webpack = require('webpack');
const path = require('path');
var precss = require('precss');
var autoprefixer = require('autoprefixer');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var postcssImport = require('postcss-import');
module.exports = {
context: __dirname + '/frontend',
devtool: 'source-map',
entry: "./index.js",
output: {
filename: 'bundle.js',
path: path.join(__dirname, './static')
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', '!css-loader?sourceMap&importLoaders=1!postcss-loader')
}
]
},
plugins: [
new ExtractTextPlugin("si-styles.css")
],
postcss: function(webpack) {
return [
postcssImport({ addDependencyTo: webpack }), // Must be first item in list
precss,
autoprefixer({ browsers: ['last 2 versions'] })
];
},
}

Categories

Resources