I'd like to use Browserify but continue loading jQuery and jQuery UI from Google's CDN instead of concatenating the code into my files or my vendor bundle. I can't seem to figure out how to get it to work.
I am getting this error when loading foo.js:
Cannot find module 'jquery-ui'
These are the relevant files:
package.json
{
// ...
"devDependencies": {
"browserify-shim": "^3.8.11",
"deamdify": "^0.1.1",
"grunt": "^0.4.5",
"grunt-browserify": "^4.0.1"
},
"dependencies": {
"jquery": "^2.1.4",
"jquery-ui": "^1.10.5"
},
"browserify-shim": {
"jquery": "global:$",
"jquery-ui": {
"depends": "jquery",
"exports": null
}
}
}
Gruntfile.js
'use strict';
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
options: {
external: [
'jquery',
'jquery-ui'
],
transform: [
'browserify-shim',
'deamdify'
]
},
app: {
files: [{
expand: true,
cwd: 'public/js',
src: '*.js',
dest: 'assets/js'
}]
}
}
});
grunt.loadNpmTasks('grunt-browserify');
};
foo.js
'use strict';
var $ = require('jquery');
require('jquery-ui');
$(document).ready(function () {
console.log('Hello world');
$('button').button();
});
I have also tried exclude instead of external and it produces the same results. Any way to achieve this?
I realize there's also the debowerify transform but I'd like to avoid Bower if possible.
Update: I've noticed that commenting out the require call to 'jquery-ui' will work because jQuery exposes the global $ and jQuery by default but I thought the whole point of writing code in CommonJS or even AMD format is to avoid depending on globals?
You do not need the external block here. That's for excluding various libraries for your bundle...which is why when using the require('jquery-ui') with the external block you're getting that error.
What you want is to expose the global jquery-ui to your browserify builds, as here in the docs.
The browserify-shim config would be:
"browserify-shim": {
"jquery": "global:$", // this is only if you're also loading jQuery via CDN/<script> tag
"jquery-ui": {
"depends": "jquery"
}
}
Related
I want to lint my scss files and scss scope in .vue components. my config in stylelint.config:
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-recess-order',
'stylelint-config-prettier',
'stylelint-config-css-modules',
],
plugins: [
'stylelint-scss',
],
rules: {},
}
and package.json:
{
"scripts": {
"lint:all:stylelint": "yarn lint:stylelint \"src/**/*.{vue,scss}\""
},
"devDependencies": {
"stylelint": "^14.1.0",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recess-order": "^3.0.0",
"stylelint-config-standard": "^24.0.0",
"stylelint-scss": "^4.0.0",
}
}
but it doesn't work. any solution?
You need to specify a custom syntax using the customSyntax option when linting anything other than CSS with Stylelint.
However, rather than use the customSyntax option yourself, you can extend shared configs that do it for you:
module.exports = {
extends: [
'stylelint-config-standard-scss', // configure for SCSS
'stylelint-config-recommended-vue', // add overrides for .Vue files
'stylelint-config-recess-order', // use the recess order for properties
'stylelint-config-css-modules', // configure for CSS Modules methodology
'stylelint-config-prettier' // turn off any rules that conflict with Prettier
]
}
The stylelint-config-standard-scss and stylelint-config-recommended-vue shared configs will configure Stylelint for SCSS and Vue files, respectively.
You don't need to include the stylelint-scss plugin yourself either, as that also comes in stylelint-config-standard-scss.
Webpack provides the example below in its shimming documentation. In the global exports portion of that page, it gives the following example.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: require.resolve('globals.js'),
use: exports-loader?file,parse=helpers.parse
}
]
}
}
./src/globals.js
var file = 'blah.txt';
var helpers = {
test: function() { console.log('test something'); },
parse: function() { console.log('parse something'); }
};
But when I attempt to build, I get:
ERROR in ./webpack.config.js
Module not found: Error: Can't resolve 'globals.js' in '/workspace/my-app'
Why is globals.js not resolving, and why does the example in their documentation assume it will? Am I missing something? Thanks.
Getting this to work with a global exports-loader configuration
I have this working with the following setup:
src/deps.js // this file just declare a global file variable
const file = 'this is the file';
src/app.js // entry point of the webpack bundle. It import's deps.js (even if deps.js does not have an export statement, thanks to export-loader):
import file from './deps.js'
console.log(file);
webpack.config.js // webpack configuration file
module.exports = {
entry: __dirname + '/src/app.js',
mode: 'development',
module: {
rules: [
{
test: /deps.js/,
use: 'exports-loader?file',
}
]
}
}
package.json // so we can run webpack locally to the project
{
"name": "exports-loader-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"webpack": "node_modules/webpack/bin/webpack.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"exports-loader": "^0.7.0",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
}
}
With this setup, assuming webpack.config.js, package.json and src/ are in the root of the project, do:
$ npm run webpack
To bundle the scripts, then:
$ node dist/main.js to check that the file variable is being loaded (to load this in a browser will do the same).
Getting this to work with an import specific configuration.
(this comes from this other answer).
In order to do so, you need to use just the exports-loader, without any further configuration when you load it in the webpack.config.js:
use: 'exports-loader',
And then specify the variables to wrap in an export clause in every import statement:
import file from 'exports-loader?file!./deps.js'
Why the require.resolve() syntax is not working?
I really don't know. The test clause expects a regex as far as I know (that's why it is called test in fact, because of the test method of regex's in javascript) and I'm not used to other kind of valid syntaxes. I see that in your snippet:
module.exports = {
module: {
rules: [
{
test: require.resolve('globals.js'),
use: exports-loader?file,parse=helpers.parse
}
]
}
}
The use value does not have string quotes. I wonder if this is broking the config and then you get a misleading error, I don't know. I actually believe you just didn't paste the quotes when copy and pasting to stack overflow.
I have directory structure as below
apps
|--GruntFile.js
|--package.json
|--js
|--js.txt
|--global
|--backbone.js
|--jquery.js
|--lodash.js
|--base.js
|--css
|--a.css
|--b.css
|--c.css
And have gruntFile.js as below:
module.exports = function(grunt){
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jsFiles: grunt.file.read('apps/js.txt'),
concat: {
options: {
separator: ';'
},
dist: {
src: [ '<%= jsFiles %>' ],
dest: 'build/js/main_base.js'
}
},
});
grunt.registerTask('default', ['concat']);
};
My js.txt file contains js files list, which needed to be processed in sequence.
js.txt:
'assets/js/global/lodash.js',
'assets/js/global/underscore.js',
'assets/js/global/backbone.js',
'assets/js/base.js
And my package.json is below:
{
"name": "abc",
"version": "1.0.0",
"author": "Allen",
"private": true,
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-concat": "^1.0.0",
"grunt-contrib-cssmin": "^1.0.0",
"grunt-contrib-handlebars": "^1.0.0",
"grunt-contrib-less": "^1.2.0",
"grunt-contrib-uglify": "^1.0.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-cssc": "^0.2.6",
"grunt-htmlhint": "^0.9.12-fix",
"matchdep": "^1.0.1"
},
}
Now when i am compiling the files using grunt file, it is getting compile successfully, but the main_base.js in build folder is of size 0.
Actually my concept goes like this, whatever the js files i am adding in my repo, i am maintaining it sequentially in js.txt , rather than maintaining them in GruntFile.js in concat task. Similar thing i want to do will all my less files.
But it is not getting process. Any idea, where i am missing? Thanks.
According to your structure I guess:
grunt.file.read('apps/js.txt'),
should be:
grunt.file.read('js/js.txt'),
and instead of:
[ '<%= jsFiles %>' ],
you should probably have:
<%= jsFiles.toString().split("\n") %>,
to create an array out of the files (convert buffer to string, convert to array based on linebreaks)
maybe you could include the jsFiles array in your grunt file, or have it as an json file to simplify parsing.
I would suggest that you check out webpack, this is what I currently use to build my apps these days, and require the modules you need directly from your javascript source files.
I recently started using grunt and can't seem to get it working: I installed grunt-cli using npm and also installed a few grunt modules using npm with no issues. I'm trying to compile all the bootstrap framework's less files into one css file but keep getting an error saying the less task was not found. i'm sure everything is where it's supposed to be and I loaded the grunt-contrib-less plugin in the gruntfile. Any idea where I might be going wrong?
My package.json's contents:
{
"name": "dConference",
"version": "0.1.0",
"devDependencies": {
"grunt": "latest",
"grunt-contrib-jshint": "latest",
"jshint-stylish": "latest",
"grunt-contrib-uglify": "latest",
"grunt-contrib-less": "latest",
"grunt-contrib-cssmin": "latest",
"grunt-contrib-watch": "latest"
}
}
And my gruntfile.js's contents:
//gruntfile specifying all tasks to be performed
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
//all configuration goes here
less: {
build: {
files: [{
expand: true,
cwd: "components/less",
src: ["*.less"]
dest: "css/main.css"
} ]
}
}
});
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-watch");
};
I made Gruntfile.js as following.
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
less: {
build: {
files: {
'css/main.css': 'components/less/bootstrap.less'
}
}
}
});
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-watch");
};
And running "grunt less" on project root folder was successful.
After successful running of "grunt less" command, main.css was generated under css folder.
Project structure is:
grunt-test-project
components/less
mixins folder
all other bootstrap less files
css
Gruntfile.js
package.json
Please try it on your side and let me know the result.
In version 2.0.2 of grunt-browserify, browserify-shim was removed from the module itself and converted to be used as a transform, rather than a straightforward option on a grunt-browserify task.
The old version of using the shim with grunt-browserify would look as such:
'libs-dev': {
src: [path.join('<%= config.dirs.browserLibs %>', 'angular', 'angular.js')],
dest: path.join('<%= config.dirs.dest.dev %>', 'js', 'libs.js'),
options: {
shim: {
angular: {
path: path.join('<%= config.dirs.browserLibs %>', 'angular', 'angular.js'),
exports: 'angular'
}
}
}
}
This worked great, and generated a wrapper around the libs.js module as such:
require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({"angular":[function(require,module,exports){
module.exports=require('i10PRm');
},{}],"i10PRm":[function(require,module,exports){
(function(global){(function browserifyShim(module, exports, define, browserify_shim__define__module__export__) {
browserify_shim__define__module__export__(typeof angular != "undefined" ? angular : window.angular);
}).call(global, undefined, undefined, undefined, function defineExport(ex) { module.exports = ex; });
})(window)
},{}]},{},["i10PRm"]);
However, based on the (incredibly sparse and frustrating) documentation, the new version of the shim within grunt-browserify is used as a transform, as such:
'libs-dev': {
src: [path.join('<%= config.dirs.browserLibs %>', 'angular', 'angular.js')],
dest: path.join('<%= config.dirs.dest.dev %>', 'js', 'libs.js'),
options: {
transform: ['browserify-shim']
}
}
and, since browserify-shim's configuration is now entirely based on package.json configuration, my package.json looks as such:
"browser": {
"angular": "./bower_components/angular/angular.js"
},
"browserify-shim": {
"angular": "angular"
}
However, this generates a wrapper that looks like:
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function (global){
__browserify_shim_require__=require;(function browserifyShim(module, exports, require, define, browserify_shim__define__module__export__) {
browserify_shim__define__module__export__(typeof angular != "undefined" ? angular : window.angular);
}).call(global, undefined, undefined, undefined, undefined, function defineExport(ex) { module.exports = ex; });
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1]);
As you can see, something's missing from this new wrapper; there doesn't seem to be an equivalent to the i10PRm export value assigned in the old wrapper. Presumably, this means I'm using exports incorrectly somehow, though I'm following the browserify-shim docs and it all seems fairly straightforward.
Would love any assistance or clarity regarding the newest versions of grunt-browserify (>= 2.0.2) and browserify-shim and how to use them together correctly.
Just an update for posterity's sake: I ended up ditching grunt-browserify and just using browserify-shim with browserify from the command-line. It works instantly with no issues at all.
I've come to the belief that the combination of the three libs (browserify, grunt-browserify, and browserify-shim) are all simply being updated and changed too rapidly to be able to rely upon them working together as they're updated. Ditching the grunt component makes the remaining two much easier to manage.
The creator of browserify-shim seems to agree:
...in my experience whenever people wrap browserify and browserify-shim (both of which are perfectly configurable in package.json) inside a task runner, they are making their life a bit harder.
I struggled with this set up too, but I managed to get it working by completely removing the shim settings from my Gruntfile.js and letting browserify handle them in package.json. Here I'm using the shim with jquery, you can also see the versions I have running below:
// portion of package.json
"browser": {
"jquery": "./js/lib/jquery-1.11.0.min.js"
},
"browserify-shim": {
"jquery": "$"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-cli": "~0.1.10",
"browserify": "~3.44.2",
"browserify-shim": "~3.4.1",
"grunt-browserify": "~2.0.8"
}
The relevant part of my Gruntfile.js now looks like this:
// portion of Gruntfile.js
browserify: {
bundleOptions: {
debug: true
},
src: 'js/src/main.js',
dest: 'js/output.js'
},
grunt:browserify now works as expected, by calling browserify but allowing it to handle browserify-shim by itself.
Donot run browserify via grunt watch, this will not reflect changes done by you in middle.
So instead whenever you change package.json file, run browserify task by grunt broswerify