Require a jQuery-Plugin with Webpack - jquery-plugins

I want to use Webpack in order to create one single scripts.js file out of all needed Javascript files.
Within my main.js I require three modules:
require('jquery');
require('readmore');
require('foundation');
My webpack.config.js is this:
var path = require('path');
module.exports = {
entry: ["./js/main.js"],
output: {
path: path.resolve(__dirname, 'build'),
filename: "scripts.js"
},
resolve: {
modulesDirectories: ["bower_components", "node_modules"],
alias: {
jquery: '../bower_components/jquery/dist/jquery.js',
readmore: '../node_modules/readmore-js/readmore.js',
foundation: '../bower_components/foundation-sites/dist/js/foundation.js'
}
}
}
My problem: as readmore-js is a jQuery-Plugin it requires jQuery by itself.
I got this error after running Webpack:
ERROR in ./~/readmore-js/readmore.js
Module not found: Error: Can't resolve 'jquery' in '/Users/myName/www/myProject/node_modules/readmore-js'
# ./~/readmore-js/readmore.js 17:4-31
# ./js/main.js
# multi main
From my understanding the problem is that readmore also wants to load the module jQuery within the directory "nodes_modules". My first approach was to resolve this problem by adding moduleDirectories to the config-file, but it does still not work.
And even in this case, the plugin shouldn't load jQuery again.
Do you have any idea how I can load jQuery globally and then "tell" all modules which require jQuery by themself "look, it's there!"
As it may helps, the following is copied out of the plugin's readmore.js:
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}

You can use webpack.ProvidePlugin for this:
Remove require jquery from main.js:
require('readmore');
require('foundation');
Configure webpack.ProvidePlugin inside webpack.config.js:
var path = require('path');
module.exports = {
entry: ["./js/main.js"],
output: {
path: path.resolve(__dirname, 'build'),
filename: "scripts.js"
},
resolve: {
modulesDirectories: ["bower_components", "node_modules"],
alias: {
readmore: '../node_modules/readmore-js/readmore.js',
foundation: '../bower_components/foundation-sites/dist/js/foundation.js'
}
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
]
}

Related

Cypress 10 config file with Cucumber

After I migrated Cypress to version 10, Cucumber preprocessor stopped to work. I have found some solutions that I implemented and I also installed the latest #badeball/cypress-cucumber-preprocessor.
Now I am stuck how to set up the cypress.config.js file, as the original plugins folder is deprecated.
In old index.js under plugin folder I had:
const cucumber = require("cypress-cucumber-preprocessor").default;
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on("file:preprocessor", cucumber());
...
Now the plugin setup should be in cypress-config.js:
e2e: {
baseUrl: 'http://localhost:4200',
specPattern: 'cypress/e2e/features',
setupNodeEvents(on, config) {
const addCucumberPreprocessorPlugin =
require('#badeball/cypress-cucumber-preprocessor').addCucumberPreprocessorPlugin;
on('file:preprocessor', addCucumberPreprocessorPlugin(on, config));
}
},
but now I have an error in on('file:preprocessor', addCucumberPreprocessorPlugin()); that addCucumberPreprocessorPlugin is not a function. I know it is not, but how to correctly configure this section for cucumber? I did not find any info about this.
If I just remove the on('file:preprocessor', addCucumberPreprocessorPlugin(on, config));, after I execute the feature test file, I have this error:
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file
The pattern I'm using is
import { defineConfig } from "cypress";
const preprocessor = require("#badeball/cypress-cucumber-preprocessor");
async function setupNodeEvents(on, config) {
await preprocessor.addCucumberPreprocessorPlugin(on, config);
// webpack config goes here if required
return config;
}
module.exports = defineConfig({
e2e: {
specPattern: "**/*.feature",
supportFile: false,
setupNodeEvents,
},
});
You may need some webpack config as well, the repository has some examples here
Here's another config that's working for me
const { defineConfig } = require("cypress");
const createBundler = require("#bahmutov/cypress-esbuild-preprocessor");
const preprocessor = require("#badeball/cypress-cucumber-preprocessor");
const createEsbuildPlugin = require("#badeball/cypress-cucumber-preprocessor/esbuild");
async function setupNodeEvents(on, config) {
await preprocessor.addCucumberPreprocessorPlugin(on, config);
on(
"file:preprocessor",
createBundler({
plugins: [createEsbuildPlugin.default(config)],
})
);
// Make sure to return the config object as it might have been modified by the plugin.
return config;
}
module.exports = defineConfig({
e2e: {
specPattern: "**/*.feature",
supportFile: false,
setupNodeEvents,
},
});
You can try this:
Install two dependencies #bahmutov/cypress-esbuild-preprocessor and #esbuild-plugins/node-modules-polyfill using:
npm install -D #bahmutov/cypress-esbuild-preprocessor
npm install -D #esbuild-plugins/node-modules-polyfill
In your cypress/plugin/index.js, remove:
const cucumber = require('cypress-cucumber-preprocessor').default
module.exports = (on, config) => {
on('file:preprocessor', cucumber()) //For cypress cucumber preprocessor
}
and Add,
//For Cucumber Integration
const createEsbuildPlugin =
require('#badeball/cypress-cucumber-preprocessor/esbuild').createEsbuildPlugin
const createBundler = require('#bahmutov/cypress-esbuild-preprocessor')
const nodePolyfills =
require('#esbuild-plugins/node-modules-polyfill').NodeModulesPolyfillPlugin
const addCucumberPreprocessorPlugin =
require('#badeball/cypress-cucumber-preprocessor').addCucumberPreprocessorPlugin
module.exports = async (on, config) => {
await addCucumberPreprocessorPlugin(on, config) // to allow json to be produced
// To use esBuild for the bundler when preprocessing
on(
'file:preprocessor',
createBundler({
plugins: [nodePolyfills(), createEsbuildPlugin(config)],
})
)
return config
}
In your package.json, add:
"cypress-cucumber-preprocessor": {
"stepDefinitions": "cypress/e2e/path-to-step-definition/**/*.{js,ts}"
}
Next, in the step definition file replace import { Given, When, Then } from ‘cypress-cucumber-preprocessor/steps’
with
import { Given, When, Then, And } from “#badeball/cypress-cucumber-preprocessor”.
For your feature files to be recognised by the cypress test runner, update the specPattern in cypress.config.js file to [“**/*.feature”, “cypress/e2e/**/*.cy.{js,jsx,ts,tsx}”].
In case anyone else gets to this solution but is using webpack and typescript I had to make a few tweaks to our existing tsconfig.json:
"esModuleInterop": false,
"noEmit": false,
Aside from that the Cypress 10 conversion tool and the examples from the #badeball/cypress-cucumber-preproccesor docs for webpack/ts were all I needed.

Unexpected token error when using Vue-pdf

I'm creating an SPA with Laravel and Vue and am trying to use vue-pdf. I've successfully integrated several npm packages, but this one is giving me the error:
Uncaught SyntaxError: Unexpected token '<'
When I click on the file (worker.js) in my console, it looks like it's trying to perform a get request for a regular page on my site instead of grabbing the javascript so my hunch is that webpack isn't correctly transpiling vue-pdf. My current webpack config is:
const path = require('path')
const fs = require('fs-extra')
const mix = require('laravel-mix')
require('laravel-mix-versionhash')
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
mix
.js('resources/js/app.js', 'public/dist/js')
.sass('resources/sass/app.scss', 'public/dist/css')
.sass('resources/sass/flowy.scss', 'public/dist/css')
mix.babel([
'resources/js/helpers/Date.js',
'resources/js/helpers/LoginRedirect.js'
], 'public/assets/js/combined.js')
.disableNotifications()
if (mix.inProduction()) {
mix
// .extract()
// .version()
.versionHash()
} else {
mix.sourceMaps()
}
mix.webpackConfig({
plugins: [
// new BundleAnalyzerPlugin()
],
resolve: {
extensions: ['.js', '.json', '.vue'],
alias: {
'~': path.join(__dirname, './resources/js')
}
},
output: {
chunkFilename: 'dist/js/[chunkhash].js',
path: mix.config.hmr ? '/' : path.resolve(__dirname, './public/build')
}
})
mix.then(() => {
if (!mix.config.hmr) {
process.nextTick(() => publishAseets())
}
})
function publishAseets () {
const publicDir = path.resolve(__dirname, './public')
if (mix.inProduction()) {
fs.removeSync(path.join(publicDir, 'dist'))
}
fs.copySync(path.join(publicDir, 'build', 'dist'), path.join(publicDir, 'dist'))
fs.removeSync(path.join(publicDir, 'build'))
}
Any help would be appreciated.

how to run vue app in the same domain with laravel sanctum for SPA

I need help in running my Vue spa in the same domain as my laravel app , when running "npm run serve" in terminal I think it's working but when I go to the browser it's refusing connection. I haven't done the backend which I will use sanctum for handling API. Has anybody here have the same project working on like me? love to make conversations to solve this.
Thanks in advance
here is the vue.config.js file
const path = require('path')
const webpack = require('webpack')
const createThemeColorReplacerPlugin = require('./config/plugin.config')
function resolve (dir) {
return path.join(__dirname, dir)
}
/**
* check production or preview(pro.loacg.com only)
* #returns {boolean}
*/
function isProd () {
return process.env.NODE_ENV === 'production'
}
const assetsCDN = {
css: [],
// https://unpkg.com/browse/vue#2.6.10/
js: [
'//cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.min.js',
'//cdn.jsdelivr.net/npm/vue-router#3.1.3/dist/vue-router.min.js',
'//cdn.jsdelivr.net/npm/vuex#3.1.1/dist/vuex.min.js',
'//cdn.jsdelivr.net/npm/axios#0.19.0/dist/axios.min.js'
]
}
// webpack build externals
const prodExternals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios'
}
// vue.config.js
const vueConfig = {
configureWebpack: {
// webpack plugins
plugins: [
// Ignore all locale files of moment.js
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],
// if prod is on, add externals
externals: isProd() ? prodExternals : {}
},
chainWebpack: (config) => {
config.resolve.alias
.set('#$', resolve('src'))
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.oneOf('inline')
.resourceQuery(/inline/)
.use('vue-svg-icon-loader')
.loader('vue-svg-icon-loader')
.end()
.end()
.oneOf('external')
.use('file-loader')
.loader('file-loader')
.options({
name: 'assets/[name].[hash:8].[ext]'
})
// if prod is on
// assets require on cdn
if (isProd()) {
config.plugin('html').tap(args => {
args[0].cdn = assetsCDN
return args
})
}
},
css: {
loaderOptions: {
less: {
modifyVars: {
// less vars,customize ant design theme
'primary-color': '#00B4E4',
// 'link-color': '#F5222D',
'border-radius-base': '4px'
},
javascriptEnabled: true
}
}
},
}
if (process.env.VUE_APP_PREVIEW === 'true') {
vueConfig.configureWebpack.plugins.push(createThemeColorReplacerPlugin())
}
module.exports = vueConfig
module.exports = {
devServer: {
host: 'app.paymate-ui.test'
}
}
If I understand you correctly, you want to use Laravel and Vue.js together in the same application folder?
Should be pretty easy then.
First off, build your application with Vue scaffolding for the frontend.
Then, make a route that redirects everything to a single controller method that returns a spa view. (Or use a closure)
In this view, include your app.js as an asset and include the main Vue component (something like <app></app>).
Then build your Vue app. All requests will now be forwarded to the spa view, which includes your app.js, which should bootstrap Vue.

Nuxt.js app deployed to Heroku only has TailwindCSS's styles for < SM breakpoint

I deployed my 1st Nuxt.js app to Heroku...Everything went smooth but when I opened the app I realised that every .vue file/component has TailwindCSS styles up untill SM breakpoint. Mobile view is fine, but anything bigger than SM breakpoint is not apllied. I also used Purgecss to remove unused styles but not sure if that can cause the problems... Any ideas on how to fix this?
I fixed my problem just by finding this https://github.com/nuxt/nuxt.js/issues/2262
I created modules folder and added import-tailwind-config.js with the code:
module.exports = function () {
const tailwindConfig = require('#nuxtjs/tailwindcss')
this.options.env.tailwind = tailwindConfig
}
And inside nuxt.config.js, outside of module.exports I added
const PurgecssPlugin = require('purgecss-webpack-plugin')
const glob = require('glob-all')
const path = require('path')
class TailwindExtractor {
static extract (content) {
return content.match(/[A-z0-9-:/]+/g) || []
}
}
As well as this code inside of module.exports
build: {
extend (config, ctx) {
config.plugins.push(
new PurgecssPlugin({
whitelist: ['html', 'body'],
paths: glob.sync([
path.join(__dirname, 'components/**/*.vue'),
path.join(__dirname, 'layouts/**/*.vue'),
path.join(__dirname, 'pages/**/*.vue'),
path.join(__dirname, 'plugins/**/*.vue')
]),
extractors: [{
extractor: TailwindExtractor,
extensions: ['html', 'js', 'vue']
}]
})
)
}
}
modules: [
'~modules/import-tailwind-config'
]

Module name “lib/chai” has not been loaded yet for context: use require([])

it is working well with karma-jasmine.....but not working with karma-mocha...y??
module.exports = function(config){
config.set({
basePath : '../app',
preprocessors: {
'**/*.html':'ng-html2js'
},
ngHtml2JsPreprocessor: {
prependPrefix: '/'
},
files : [
'node_modules/jquery/**/*.js',
'lib/angular/angular.js',
'lib/angular/angular-*.js',
'../test/lib/angular-mocks.js',
'../test/lib/sinon-1.15.0.js',
'../test/lib/chai.js',
'js/**/*.js',
'../test/unit/**/*.js',
'**/*.html'
],
autoWatch : true,
frameworks: ['mocha','requirejs','chai'],
browsers : ['Chrome'],
plugins : [
'karma-chrome-launcher',
'karma-mocha',
'karma-ng-html2js-preprocessor',
'karma-requirejs',
'karma-chai'
],
junitReporter : {
outputFile: 'test_out/unit.xml',
suite: 'unit'
}
});
};
MY SAMPLE CODE:::
'use strict';
describe('calendarHelper', function() {
beforeEach(module('eventsApp'));
it('should return January when given a zero', inject(function(calendarHelper) {
expect(calendarHelper.getMonthName(0)).toBe('January');
}))
});
I came across a similar situation just with Jasmine.
I'd like to introduce my solution.
Try it what is written in the error message. There is a link to a website: http://requirejs.org/docs/errors.html#notloaded
Use this in your spec file:
//If this code is not in a define call,
//DO NOT use require('foo'), but use the async
//callback version:
require(['foo'], function (foo) {
//foo is now loaded.
});
My case written for Jasmine and Sinon in Coffeescript looks like this:
sinon = require(['sinon', 'jasmine-sinon']) (foo)->
Now I can use sinon as an object in my unit test and can also follow the documentation of sinon, as well as jasmin-sinon.

Resources