How to use webpack loaders in nuxt.js? - javascript

I am trying to use https://github.com/itgalaxy/webpack-modernizr-loader this loader in my nuxt/webpack project.
Unfortunately loaders are added differently than with a normal webpack project and I don't really understand nuxt's documentation on this issue:
https://nuxtjs.org/api/configuration-build#loaders
I have a sample repo with a minimal nuxt project:
https://github.com/Jones-S/nuxt-modernizr
In my nuxt.config.js (equivalent to webpack config)
I tried to include the loader and use in my pages/index.vue.
Unfortunately I am getting an error that I have modernizr not installed.
This can't be the case though.
I would be really happy if somebody could have short look into this and tell me how I correctly use loaders in nuxt.js.
For brevity my part of the nuxt.config.js
build: {
/*
** You can extend webpack config here
*/
extend(config, { isDev, isClient }) {
// Run ESLint on save
if (isDev && isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
config.module.rules.push({
test: /\.modernizrrc\.js$/,
use: { loader: 'webpack-modernizr-loader' }
})
config.resolve.alias['modernizr'] = '/.modernizrrc.js'
}
}
}
I am pushing the new loader and register an alias below. But I would get this error:
ERROR Failed to compile with 1 errors
This dependency was not found:
* modernizr in ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js&
To install it, you can run: npm install --save modernizr
thank you very much in advance.
cheers

Related

Use Template Strings with webpack [Javascript]

I'm fairly new to webpack, and when compiling my code I came across this error.
ERROR in Error: Child compilation failed:
Module build failed (from ../node_modules/html-loader/index.js):
Error: Line 539: Unexpected identifier
And this is the line that its referring too.
return `background: linear-gradient(to bottom right, ${this.gradientStart}, ${this.gradientEnd});`
Is it possible to allow Template Strings in Webpack?
This is the inside of my webpack config
const html = {
test: /\.(html)$/,
// exclude: /\.html$/,
use: [
{
loader: 'html-loader',
options: {
interpolate: true,
},
},
],
};
Template strings are a feature of es2015. Webpack does not understand es2015 by default to ensure compatibility with as many legacy devices as possible. You need to use a loader that will transpile es2015 into an older version of javascript. You can use "babel-loader" with the preset webpack environment that has support for many features of modern javascript.
You need to download #babel/core & #babel/preset-env for webpack by running the following command:
npm install --save-dev -D babel-loader #babel/core #babel/preset-env webpack
You need to add the following to your webpack.config.js
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
},

webpack how to run babel-loader on files outside the project directory?

I am using webpack2, babel-loader
import something from '../../customPackageOutsideProjectDirectory';
the above line of code gives the following error:
Module build failed: Error: Parse Error: Line 1: Illegal import declaration
at throwError (/Users/sahilsharma/workspace/projectTry/node_modules/jstransform/node_modules/esprima-fb/esprima.js:2823:21)
The error is probably because of lack of .babelrc file outside the project directory.
How to get this package loaded correctly from outside ?
The .babelrc file isn't necessary if you config Babel in webpack using the options:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
]
}
https://github.com/babel/babel-loader

webpack bundle size vs requirejs bundle size

I'm trying to migrate a requireJS based app to webpack.
This app doesn't have many dependencies - actually it only needs a promise polyfill - and I've already figured out how to make webpack using the minified one.
The bundle size with requireJS used to be 43KB, when using webpack it's 121KB.
While 121KB isn't really huge it is a notable size increase.
From running webpack --display-reasons --display-modules I have learned that there seems to be some node_module dependencies included in my bundle. Way more than I expected.
I see things like buffer, readable-stream, stream-http, stream-browserify, core-util-is, buffer-shims, ...
Is this expected / part of the webpack wrapper code?
Is there anything I can do to exclude these dependencies?
This is my webpack.config.js:
var webpack = require('webpack');
module.exports = {
entry: {
"mynexuz": "./js/mynexuz-api.js",
"kws": "./js/kws-api.js",
"main": "./js/main.js",
"quest": "./js/quest.js"
},
output: {
filename: "./dist/[name]-bundle.js",
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production'),
}
})
],
node: {
//stream: false,
//process: false,
//global: false
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
modules: ['js', 'js/lib', 'node_modules'],
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
test: /\.js$/,
loader: "source-map-loader",
exclude: /node_modules/
},
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{
test: /\.tsx?$/,
loader: "awesome-typescript-loader",
exclude: /node_modules/
}
]
},
};
This doesn't work for all libraries you are using, but when possible you can save on file size by only importing the actual function/component you need to use.
Here is an example with lodash
import has from 'lodash/has';
That way above will ONLY import the has method.
However if you do either of the following:
import { has } from 'lodash';
Or
import _ from 'lodash';
Then you will import ALL of the lodash library which will bump up your file size.
However with other libraries (i.e. current version of moment.js) it's not so simple to import just the PART of the library you need.
There are a few other ways to try to solve this problem (i.e. tweaking your webpack settings) but I would start with this method.
After looking deeper into the issue I've found the reason for the large size of the bundle. In true requireJS style I had:
define(['http', 'config'], function (Http, Config) { ... });
This 'http' thing was supposed to refer to my own library, but webpack resolved this to some NPM module, bringing in all the aforementioned dependencies.
I've now changed the code to:
define(['./http', 'config'], function (Http, Config) { ... });
And the bundle sizes are back to around 44KB.

npm link with webpack - cannot find module

I'm trying to npm link a module to a project using webpack as its bundler. Of course, after trying many things, I keep getting this error:
ERROR in ./src/components/store/TableView.jsx
Module not found: Error: Cannot resolve module 'react-bootstrap-table'
Here are the exact steps I take when doing this:
1.) cd ../forks/react-bootstrap-table
2.) npm link
(success, checked ~/.nvm/.../node_modules/react-bootstrap-table for symlink and it's there)
3.) cd ../../projRoot/
4.) npm link react-bootstrap-table
(no errors thrown?, says successful link)
5.) node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js
Solutions I've tried:
- https://webpack.github.io/docs/troubleshooting.html
- How to make a linked component peerDepdencies use the equivalent node_modules of the script being linked to?
- And many purple links on google serps
webpack.config.js
const webpack = require('webpack')
const path = require('path')
const ROOT_PATH = path.resolve(__dirname)
module.exports = {
devtool: process.env.NODE_ENV === 'production' ? '' : 'source-map',
entry: [
'webpack/hot/only-dev-server',
'./src/index.js'
],
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot','babel']
},
{
test: /\.scss$/,
loaders: ['style','css','sass'],
exclude: /node_modules/
},
{
test: /\.css$/,
loaders: ['style','css']
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
fallback: path.resolve(__dirname, './node_modules')
},
resolveLoader: {
fallback: path.resolve(__dirname, './node_modules')
},
output: {
path: process.env.NODE_ENV === 'production' ? path.resolve(ROOT_PATH, 'app/dist') : path.resolve(ROOT_PATH, 'app/build'),
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(ROOT_PATH),
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
stats: 'errors-only',
host: '192.168.1.115'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
Notes:
1. this is the only symlink in the project
2. I run npm install inside forked version (also tried without, doesn't work)
3. I use NVM, but I have used symlinks before without webpack successfully.
I've been at this for a few days now, any help will be much appreciated.
I was facing a similar issue with webpack and ended up by adding this my webpack.config.js:
module.exports = {
resolve: {
symlinks: false
}
};
Here is the link to webpack docs. Since your question there happened a lot to webpack and their api, so I do not know how much relevance my answer still has according to your question. But for people facing this or a similar issue today this could be a solution. As to be seen, there are still people complaining about:
Webpack GitHub Issue 1643
Webpack GitHub Issue 1866
Also make sure you have bundle and yarn installed and executed in the linked package
Okay guys, this is specific to my use case, but make sure to follow all the instructions to completely build the library you are symlinking. Initially, I a npm install and gulp build, but that wasn't enough. I had to run a few extra commands to get the library to fully build.
Now it works! If you are still having issues, go through the documentation for each library you are symlinking, and use my webpack config as a template for resolving external libraries.
Just in case it's useful for others, the solution of adding the resolve.symlinks configuration to false suggested by #Beat was not enough in my case, I had to perform the following steps to solve it:
In the library:
Setup the libraries that are generating issues as peerDependencies in the package.json instead of dependencies or devDependencies, e.g. in my case react:
"peerDependencies": {
"react": "^16.8.6",
...
}
run npm install
build the library (in my case, with a rollup -c npm script
In my main app:
change the version of my library to point to my local project with a relative path in package.json, e.g.
"dependencies": {
"my-library": "file:../../libraries/my-library",
...
}
Add resolve.symlinks = false to my main app's webpack configuration
Add --preserve-symlinks-main and --preserve-symlinks to my package.json start script, e.g:
"scripts": {
"build": "set WEBPACK_CONFIG_FILE=all&& webpack",
"start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
run npm install
run npm run start

How To Use ScrollMagic with GSAP and Webpack

In order to use ScrollMagic with GSAP, you need to load the animation.gsap.js plugin. With Webpack you would do something like this to accomplish that (assuming you use the CommonJS syntax and installed everything with npm):
var TweenMax = require('gsap');
var ScrollMagic = require('scrollmagic');
require('ScrollMagicGSAP');
To make sure that this actually works, you have to add an alias to your Webpack configuration, so that Webpack knows where the plugin lives.
resolve: {
alias: {
'ScrollMagicGSAP': 'scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap'
}
}
Unfortunately, ScrollMagic keeps throwing an error, when you are using this configuration and the CommonJS syntax like above.
(ScrollMagic.Scene) -> ERROR calling setTween() due to missing Plugin 'animation.gsap'. Please make sure to include plugins/animation.gsap.js
The Solution
You have to tell Webpack to stop using the AMD syntax by adding the following loader that deactivates the define() method.
// Webpack 4+
module: {
rules: [
{ parser: { amd: false }}
]
}
// Webpack <= 3
// Don’t forget to install the loader with `npm install imports-loader --save-dev`
module: {
loaders: [
{ test: /\.js$/, loader: 'imports-loader?define=>false'}
// Use this instead, if you’re running Webpack v1
// { test: /\.js$/, loader: 'imports?define=>false'}
]
}
Why?
The problem lies in the fact that Webpack supports the AMD (define) and CommonJS (require) syntax. That is why the following factory script within plugins/animation.gsap.js jumps into the first if statement and fails silently. That is why setTween() etc. are never added to the ScrollMagic Constructor.
By telling Webpack not to support the AMD syntax (using the loader mentioned above), the plugin jumps into the second if statement correctly, embracing the CommonJS syntax.
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['ScrollMagic', 'TweenMax', 'TimelineMax'], factory);
} else if (typeof exports === 'object') {
// CommonJS
// Loads whole gsap package onto global scope.
require('gsap');
factory(require('scrollmagic'), TweenMax, TimelineMax);
} else {
// Browser globals
factory(root.ScrollMagic || (root.jQuery && root.jQuery.ScrollMagic), root.TweenMax || root.TweenLite, root.TimelineMax || root.TimelineLite);
}
I hope this prevents other people from spending a whole evening trying to figure out what is going on.
The solution I came across that doesn't require you to alter your webpack.config.js file and actually works for me can be found here: https://github.com/janpaepke/ScrollMagic/issues/665
The gist of it is to make sure you have ScrollMagic and GSAP added via npm (hopefully that's obvious) as well as imports-loader:
npm install --save scrollmagic gsap
npm install --save-dev imports-loader
Then in the file you want to use ScrollMagic with GSAP do the following imports:
import { TimelineMax, TweenMax, Linear } from 'gsap';
import ScrollMagic from 'scrollmagic';
import 'imports-loader?define=>false!scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap';
Using Webpack 4.x and imports-loader 0.8.0
medoingthings solution has since changed syntax to include "-loader" suffix.
module: {
loaders: [
{ test: /\.js$/, loader: 'imports-loader?define=>false'}
]
}
https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed
In imports-loader 1.1.0, the syntax of the configuration has changed a bit, so now you have to use the following to get the ScrollMagic plugins to work:
{
test: [
path.join(config.root, '/node_modules/scrollmagic/scrollmagic/uncompressed/plugins/jquery.ScrollMagic.js'),
path.join(config.root, '/node_modules/scrollmagic/scrollmagic/uncompressed/plugins/debug.addIndicators.js')
],
use: [
{
loader: 'imports-loader',
options: {
additionalCode: 'var define = false;'
}
}
]
}
Hopefully this helps others.
I was having the same issue and found this question.
For those using Webpack 5 I believe imports-loader is out of date so according to the webpack docs add this code to your js rule to disable AMD:
{
test: /\.js$/,
include: /node_modules/,
parser: {
amd: false
}
}
documentation: https://webpack.js.org/configuration/module/#ruleparser

Categories

Resources