I'm currently trying to migrate a grunt project to a gulp project. Actually, in the gruntfile I have (for the jshint task) something like this:
jshint: {
options: {
trailing:true,
evil:false,
indent:4,
undef:true,
unused:true,
node:false,
browser:false,
loopfunc:true,
devel:false
},
default: {
options: {
browser:true,
globals: {
define:true
}
},
src: [basePath + "js/**/*.js"]
}
}
So, when I write "grunt jshint" in the terminal it seems to work fine. However, in the gulpfile I wrote this:
gulp.task("jshint", function() {
return gulp.src( basePath + "js/**/*.js" )
.pipe( jshint( { "trailing": true,..., "globals": true } ) )
.pipe( jshint.reporter("default") );
});
But when I write "gulp jshint" in terminal, it crashes.
My question is: Is there a way to send jshint parameters without .jshintrc file with the gulp-jshint node package? (I've already read the documentation in the npm site, but I dont undestand the "lookup" option)
globals is an array, not true false, here is my example. lookup works just like you were thinking.
gulp.src(files.backend)
.pipe(jshint({ "lookup": false, /* other options */ "globals": ['$']}))
.pipe(jshint.reporter(stylish))
.on('error', gutil.log);
Related
I'm using Next.js for Server Side Rendering of React application (with styled-components) and have issue with Babel plugins I'm using to show name of the components I'm using in code.
This is my .babelrc file:
{
"env": {
"development": {
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
},
"production": {
"presets": "next/babel",
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": false,
"ssr": true
}
]
]
},
"test": {
"presets": [
[
"env",
{
"modules": "commonjs"
}
],
"next/babel"
]
}
}
}
When I'm running cross-env NODE_ENV=development concurrently "tsc --watch" next
I'm getting these lines - meaning .babelrc is used during copilation:
[1] > Using external babel configuration
[1] > Location: "...../.babelrc"
[1] > Using "webpack" config function defined in next.config.js.
But once I go to dev tools and see some styled-component I can see this: class="sc-iyvyFf gGaJAt" but on my code I have this definition:
const Title = styled.div`
font-size: 40px;
line-height: 1.13;
`
As it seems from documentation example - I should get something like ... <button class="Button-asdf123 asdf123" /> instead of just <button class="asdf123" />. But I don't.
After going deeper I found this issue ( https://github.com/styled-components/styled-components/issues/1103#issuecomment-324302997 ) based on errors I get in browser console that said:
It seems that only the server code is being transpiled and not the client code 😉
So Question: How to test if babel works correctly and .babelrc is being used in all places?
P.S. In my case those classes that I've got on client side had this prefix sc- meaning in my head styled-components. So I was not sure if the plugin from .babelrc works at all or it works, but I haven't set any special property in declaration of styled-components thus get this general prefix sc-
UPDATE Here is my custom next.conf.js I'm using
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { ANALYZE } = process.env
const path = require('path')
module.exports = {
exportPathMap: function() {
return {
'/': { page: '/' }
}
},
webpack: function(config) {
if (ANALYZE) {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerPort: 8888,
openAnalyzer: true
})
)
}
config.resolve.alias = {
'styled-components': path.resolve('./node_modules/styled-components/')
}
return config
}
}
Looks like no one has unfortunately answered this before;
What you're seeing probably comes down to this little piece of code you posted: tsc --watch
If you execute TypeScript transpilation before Babel and leave it up to TypeScript to transpile to ES5, it'll transpile all tagged template literals, not giving our plugin anything to hook onto.
Since you're already using next.js you won't need to set up your Babel pipeline from scratch. Rather you only need to disable this type of transpilation in TypeScript.
I'd suggest you to set target inside your tsconfig.json to ESNext so that it leaves everything up to Babel.
https://www.typescriptlang.org/docs/handbook/compiler-options.html (See "--target")
I'm trying to build my JS-bundle via grunt/browserify. I also use grunt for scss compile. For that I use grunt-watch to trigger scss compile on changes.
I wanted the same behavior for JS-browserify. grunt-browserify comes with the "watch" option, which does the trick very well.
My only issue is: I want to get notified after a "re-browserify". For SCSS I use grunt-notify. But I do not find any way to trigger a grunt task after browserify-watch.
My gruntfile excerpt:
var gruntOptions = {
notify: {
browserify_node_modules: {
options: {
title: "Browserify",
message: "node_modules build"
}
}
},
browserify: {
node_modules: {
src: ["node_modules.js"],
dest: "trunk/js/lib/node_modules.js",
options: {
watch: true,
}
}
}
};
Best case scenario:
options: {
watch: true,
finishTask: "notify:browserify_node_modules"
}
Thanks!
You can check if the file generated by Browserify has been changed and then, trigger a task.
Install watch task in Grunt:
npm install grunt-contrib-watch --save-dev
Configure watch task within Gruntfile.js:
grunt.initConfig({
// other tasks
your_task: {
// ...
},
watch: {
dev: {
files: 'trunk/js/lib/node_modules.js', // file generated by Browserify
options: { spawn: false },
tasks: ['your_task']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
I have a problem with grunt-frontend package.
When I run grunt task I get:
Running "frontend-js:main" (frontend-js) task
Processing /assets/js/main.min.js
Warning: Cannot assign to read only property 'spidermonkey' of /assets/js/main.min.js Used --force, continuing.
What is going wrong?
I have Gruntfile.js configured like in the documentation:
'frontend-js': {
main: {
options: {
minify: true,
uglify: {}
},
files: {
'out/js/f.js': [
'test/js/file1.js',
'test/js/file2.js'
]
}
}
}
When I set minify: false everything works normally, except minification of course.
I'm learning Grunt and trying to sort out how I can create 2 versions of the same application. The difference between the two are configuration settings.
Ideally, I would like the process to output 2 versions. One with a boolean in one of the .js files set to false, the other left to true. I would also need to concat and minify then file.
Is there a recommended way to do this? Thanks in advance
You can specify 2 configurations in your grunt.initConfig
grunt.initConfig({
myTask: {
version1: { ... }
version2: { ... }
}
})
And then register your default task to run each of these versions
grunt.task.registerTask("default", ["myTask:version1", "myTask:version2"])
Or just some other task name, myTaskAllVersions instead of default
You could use this versioning to flip your .js boolean, per version 1 or 2.
A similar approach could be taken to minifying and concatting the files afterwards, i.e.
grunt.initConfig({
minify: {
version1: { ... }
version2: { ... }
}
})
and
grunt.task.registerTask("default", ["myTask:version1", "minify:version1"])
You could do all of this with the uglifyjs grunt task.
Here's an example of the config for your Gruntfile:
grunt.initConfig({
uglify: {
app1: {
files: {
'dist/app1.min.js': [
'src/app1.js',
'src/common.js'
]
}
},
app2: {
files: {
'dist/app2.min.js': [
'src/app2.js',
'src/common.js'
]
}
}
}
});
I have a couple grunt tasks and I am trying to share global variables across those tasks and I am running into issues.
I have written a some custom tasks which set the proper output path depending on the build type. This seems to be setting things correctly.
// Set Mode (local or build)
grunt.registerTask("setBuildType", "Set the build type. Either build or local", function (val) {
// grunt.log.writeln(val + " :setBuildType val");
global.buildType = val;
});
// SetOutput location
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
if (global.buildType === "tfs") {
global.outputPath = MACHINE_PATH;
}
if (global.buildType === "local") {
global.outputPath = LOCAL_PATH;
}
if (global.buildType === "release") {
global.outputPath = RELEASE_PATH;
}
if (grunt.option("target")) {
global.outputPath = grunt.option("target");
}
grunt.log.writeln("Output folder: " + global.outputPath);
});
grunt.registerTask("globalReadout", function () {
grunt.log.writeln(global.outputPath);
});
So, I'm trying to then reference global.outputPath in a subsequent task, and running into errors.
If I call grunt test from the command line, it outputs the correct path no problem.
However, if I have a task like this:
clean: {
release: {
src: global.outputPath
}
}
It throws the following error:
Warning: Cannot call method 'indexOf' of undefined Use --force to continue.
Also, my constants in the setOutput task are set at the top of my Gruntfile.js
Any thoughts? Am I doing something wrong here?
So, I was on the right path. The issue is that the module exports before those global variables get set, so they are all undefined in subsequent tasks defined within the initConfig() task.
The solution I came up with, although, there may be better, is to overwrite a grunt.option value.
I have an optional option for my task --target
working solution looks like this:
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
if (global.buildType === "tfs") {
global.outputPath = MACHINE_PATH;
}
if (global.buildType === "local") {
global.outputPath = LOCAL_PATH;
}
if (global.buildType === "release") {
global.outputPath = RELEASE_PATH;
}
if (grunt.option("target")) {
global.outputPath = grunt.option("target");
}
grunt.option("target", global.outputPath);
grunt.log.writeln("Output path: " + grunt.option("target"));
});
And the task defined in initConfig() looked like this:
clean: {
build: {
src: ["<%= grunt.option(\"target\") %>"]
}
}
Feel free to chime in if you have a better solution. Otherwise, perhaps this may help someone else.
I have a way to do this that allows you to specify the output path using values like --dev. So far it's working very well, I quite like it. Thought I'd share it, as someone else may like it, too.
# Enum for target switching behavior
TARGETS =
dev: 'dev'
dist: 'dist'
# Configurable paths and globs
buildConfig =
dist: "dist"
dev: '.devServer'
timestamp: grunt.template.today('mm-dd_HHMM')
grunt.initConfig
cfg: buildConfig
cssmin:
crunch:
options: report: 'min'
files: "<%= grunt.option('target') %>/all-min.css": "/**/*.css"
# Set the output path for built files.
# Most tasks will key off this so it is a prerequisite
setPath = ->
if grunt.option 'dev'
grunt.option 'target', buildConfig.dev
else if grunt.option 'dist'
grunt.option 'target', "#{buildConfig.dist}/#{buildConfig.timestamp}"
else # Default path
grunt.option 'target', buildConfig.dev
grunt.log.writeln "Output path set to: `#{grunt.option 'target'}`"
grunt.log.writeln "Possible targets:"
grunt.log.writeln target for target of TARGETS
setPath()
With this setup, you can run commands like:
grunt cssmin --dist #sent to dist target
grunt cssmin --dev #sent to dev target
grunt cssmin --dev #sent to default target (dev)
This is an older question, I just thought to throw in my 5 cents.
If you need config variable to be accessible from any task, just define it in your main (the one that you'll always load) config file like this:
module.exports = function(grunt)
{
//
// Common project configuration
//
var config =
{
pkg: grunt.file.readJSON('package.json'),
options: // for 'project'
{
dist:
{
outputPath: '<%= process.cwd() %>/lib',
},
dev:
{
outputPath: '<%= process.cwd() %>/build',
},
},
}
grunt.config.merge( config )
}
Then you can simply access value like this:
in config file(s)
...
my_thingie:
[
ends_up_here: '<%= options.dev.outputPath %>/bundle',
],
...
in tasks
// as raw value
grunt.config.data.options.dist.outputPath
// after (eventual) templates have been processed
grunt.config('options.dist.outputPath')
I used key options here just to be in line with convention, but you can use anything as long as you remember not to register a task named 'options' or whatever you used for the key :)