Description:
As part of a general development environment update, we decided to update some of our dev dependencies including gulp and gulp-* utilities. Our projects use Ionic v.1.3.5 with up-to-date Ionic CLI and @ionic/v1-toolkit. We updated our gulpfile.js file according to the latest version of gulp (we were using [email protected]). Once the code has been updated, we used the normal ionic serve command to start the local server. The server started up but no tasks have been executed. We run the command again but with the --verbose option. This highlighted the following issue:
[v1] 2019-08-09T14:37:54.498Z ionic:v1-toolkit:lib:gulp Using gulpfile: /Users/xxxx/dev/NEXT-MASTER-new-gulp/project/gulpfile.js
[v1] 2019-08-09T14:37:54.499Z ionic:v1-toolkit:lib:gulp Using gulp: /Users/xxxx/dev/NEXT-MASTER-new-gulp/project/node_modules/@ionic/v1-toolkit/node_modules/gulp/index.js
[v1] 2019-08-09T14:37:55.875Z ionic:v1-toolkit:lib:gulp Loaded gulp tasks: {}
[v1] [16:37:55] Serving directory www
I kept the previous version aside and ran the same command:
[v1] 2019-08-09T14:28:43.114Z ionic:v1-toolkit:lib:gulp Using gulpfile: /Users/xxxx/dev/NEXT-MASTER-old-gulp/project/gulpfile.js
[v1] 2019-08-09T14:28:43.115Z ionic:v1-toolkit:lib:gulp Using gulp: /Users/xxxx/dev/NEXT-MASTER-old-gulp/project/node_modules/gulp/index.js
[v1] 2019-08-09T14:28:44.760Z ionic:v1-toolkit:lib:gulp Loaded gulp tasks: { 'ionic:watch:before': { fn: [Function], dep: [ 'default', 'watch' ], name: 'ionic:watch:before' }, 'ionic:serve:before': { fn: [Function], dep: [ 'default', 'watch' ], name: 'ionic:serve:before' }, default: { fn: [Function], dep: [ 'build-eslint', 'img', 'fonts', 'css', 'lib', 'templateCache', 'useref', 'buildInfo' ], name: 'default' }, 'build-eslint': { fn: [Function], dep: [], name: 'build-eslint' }, img: { fn: [Function], dep: [], name: 'img' }, fonts: { fn: [Function], dep: [], name: 'fonts' }, css: { fn: [Function], dep: [], name: 'css' }, sass: { fn: [Function], dep: [ 'css' ], name: 'sass' }, lib: { fn: [Function], dep: [], name: 'lib' }, deleteUselessFiles: { fn: [Function], dep: [], name: 'deleteUselessFiles' }, templateCache: { fn: [Function], dep: [], name: 'templateCache' }, useref: { fn: [Function], dep: [], name: 'useref' }, buildInfo: { fn: [Function], dep: [], name: 'buildInfo' }, watch: { fn: [Function], dep: [], name: 'watch' }, eslint: { fn: [Function], dep: [], name: 'eslint' }, run: { fn: [Function], dep: [], name: 'run' } }
[v1] [16:28:44] Invoking ionic:serve:before gulp task.
It seemed obvious that the @ionic/v1-toolkit had trouble getting the list of available tasks. Note that in, the "new gulp version" case, it uses the gulp dependency of @ionic/v1-toolkit whereas it uses the "root" gulp dependency in the "old gulp version" case (as versions were the same).
Digging into the source, I noticed that the property tasks were read: https://github.com/ionic-team/ionic-cli/blob/84a6b7fe0bfc6cbab1a0dd1a9bd623d5556bccc5/packages/%40ionic/v1-toolkit/src/lib/gulp.ts#L43
I ran the code manually in both projects.
First with the "old gulp version":
MacBook:project xxxx$ node
> const gulpPath = require.resolve('gulp');
undefined
> require('/Users/xxxx/dev/NEXT-MASTER-old-gulp/project/gulpfile.js');
{}
> require(gulpPath);
Gulp {
domain:
Domain {
domain: null,
_events:
[Object: null prototype] {
removeListener: [Function: updateExceptionCapture],
newListener: [Function: updateExceptionCapture],
error: [Function: debugDomainError] },
_eventsCount: 3,
_maxListeners: undefined,
members: [] },
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
doneCallback: undefined,
seq: [],
tasks:
{ 'ionic:watch:before': { fn: [Function], dep: [Array], name: 'ionic:watch:before' },
'ionic:serve:before': { fn: [Function], dep: [Array], name: 'ionic:serve:before' },
default: { fn: [Function], dep: [Array], name: 'default' },
'build-eslint': { fn: [Function], dep: [], name: 'build-eslint' },
img: { fn: [Function], dep: [], name: 'img' },
fonts: { fn: [Function], dep: [], name: 'fonts' },
css: { fn: [Function], dep: [], name: 'css' },
sass: { fn: [Function], dep: [Array], name: 'sass' },
lib: { fn: [Function], dep: [], name: 'lib' },
deleteUselessFiles: { fn: [Function], dep: [], name: 'deleteUselessFiles' },
templateCache: { fn: [Function], dep: [], name: 'templateCache' },
useref: { fn: [Function], dep: [], name: 'useref' },
buildInfo: { fn: [Function], dep: [], name: 'buildInfo' },
watch: { fn: [Function], dep: [], name: 'watch' },
eslint: { fn: [Function], dep: [], name: 'eslint' },
run: { fn: [Function], dep: [], name: 'run' } },
isRunning: false }
and then with the "new gulp version":
MacBook-Pro:project xxxx$ node
> const gulpPath = require.resolve('gulp');
undefined
> require('/Users/xxxx/dev/NEXT-MASTER-new-gulp/project/gulpfile.js');
{}
> require(gulpPath);
Gulp {
domain:
Domain {
domain: null,
_events:
[Object: null prototype] {
removeListener: [Function: updateExceptionCapture],
newListener: [Function: updateExceptionCapture],
error: [Function: debugDomainError] },
_eventsCount: 3,
_maxListeners: undefined,
members: [] },
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_registry:
DefaultRegistry {
_tasks:
{ 'build-eslint': [Function],
img: [Function],
fonts: [Function],
css: [Function],
sass: [Function],
lib: [Function],
deleteUselessFiles: [Function],
templateCache: [Function],
useref: [Function],
buildInfo: [Function],
watch: [Function],
eslint: [Function],
default: [Function],
'ionic:watch:before': [Function],
'ionic:serve:before': [Function] } },
_settle: false,
watch: [Function: bound ],
task: [Function: bound task],
series: [Function: bound series],
parallel: [Function: bound parallel],
registry: [Function: bound registry],
tree: [Function: bound tree],
lastRun: [Function: bound lastRun],
src: [Function: bound src],
dest: [Function: bound dest],
symlink: [Function: bound symlink] }
The path to access the list of tasks is different with the latest version of Gulp.
Steps to Reproduce:
See description above.
Output:
See description above.
My ionic info:
Ionic:
Ionic CLI : 5.2.4 (/usr/local/lib/node_modules/ionic)
Ionic Framework : ionic1 1.3.5
@ionic/v1-toolkit : 2.0.7
Cordova:
Cordova CLI : 9.0.0 ([email protected])
Cordova Platforms : none
Cordova Plugins : no whitelisted plugins (0 plugins total)
Utility:
cordova-res : 0.6.0
native-run : 0.2.8
System:
ios-sim : 8.0.1
NodeJS : v10.15.3 (/usr/local/bin/node)
npm : 6.10.3
OS : macOS Mojave
Xcode : Xcode 10.3 Build version 10G8
Other Information:
If this might help, devDependencies for the "old gulp version" case:
"devDependencies": {
"@ionic/lab": "2.0.7",
"@ionic/v1-toolkit": "2.0.7",
"colour": "0.7.1",
"cordova-lib": "9.0.1",
"del": "3.0.0",
"gulp": "3.9.1",
"gulp-angular-templatecache": "2.2.0",
"gulp-clean-css": "3.9.2",
"gulp-eslint": "4.0.2",
"gulp-file": "0.4.0",
"gulp-htmlmin": "4.0.0",
"gulp-if": "2.0.2",
"gulp-ng-annotate": "2.1.0",
"gulp-rename": "1.2.2",
"gulp-sass": "3.1.0",
"gulp-uglify": "3.0.0",
"gulp-useref": "3.1.4",
"gulp-util": "3.0.8"
},
and for the "new gulp version" case:
"devDependencies": {
"@ionic/lab": "2.0.7",
"@ionic/v1-toolkit": "2.0.7",
"colour": "0.7.1",
"del": "5.0.0",
"gulp": "4.0.2",
"gulp-angular-templatecache": "3.0.0",
"gulp-clean-css": "4.2.0",
"gulp-eslint": "6.0.0",
"gulp-file": "0.4.0",
"gulp-htmlmin": "5.0.1",
"gulp-if": "3.0.0",
"gulp-ng-annotate": "2.1.0",
"gulp-rename": "1.4.0",
"gulp-sass": "4.0.2",
"gulp-uglify": "3.0.2",
"gulp-useref": "3.1.6",
"fancy-log": "1.3.3",
"ansi-colors": "4.1.1"
},
@CheetahDev I figured it out! If you run npm ls gulp with the new version, you'll see that there are 2 separate versions of gulp installed. The problem is that when you run ionic build, it loads gulp from the v1-toolkit, in which gulp fails to find any tasks for some reason. We need to enforce that gulp should only live on the project's node-modules/ folder.
To do that, run the following commands below:
npm install --save-dev [email protected] # install gulp version 3.9.1
npm dedupe # remove any duplicate installations of gulp
Make sure to lock your dependency of gulp in your project's package.json!
Hmm... gulp should probably be a peer dependency of @ionic/v1-toolkit, not an actual dependency.
same here..
my ionic info :
Ionic CLI : 5.2.4 (C:\Users\Phincon\AppData\Roaming\npm\node_modules\ionic)
Ionic Framework : ionic1 1.3.1
@ionic/v1-toolkit : 1.0.22
Cordova:
Cordova CLI : 8.1.2 ([email protected])
Cordova Platforms : android 7.1.4
Cordova Plugins : no whitelisted plugins (6 plugins total)
Utility:
cordova-res : not installed
native-run : not installed
System:
Android SDK Tools : 26.1.1 (C:\Users\Phincon\AppData\Local\Android\Sdk)
NodeJS : v10.16.2 (C:\Program Files\nodejs\node.exe)
npm : 6.10.3
OS : Windows 10
my package.json :
"dependencies": {
"@ionic-native/market": "^4.15.0",
"cordova-android": "7.1.4",
"cordova-plugin-camera": "^4.0.3",
"cordova-plugin-compat": "^1.2.0",
"cordova-plugin-geolocation": "^2.4.3",
"cordova-plugin-market": "1.2.0",
"cordova-plugin-whitelist": "^1.3.3",
"cordova-uglify": "^0.3.3",
"ion-datetime-picker": "^0.5.2",
"ionic-select-searchable": "^1.1.3"
},
"devDependencies": {
"@ionic/v1-toolkit": "^1.0.22",
"async": "^2.6.1",
"bower": "^1.3.3",
"gulp": "^4.0.0",
"gulp-angular-templatecache": "^3.0.0",
"gulp-concat": "^2.2.0",
"gulp-debug": "^4.0.0",
"gulp-minify-css": "^0.3.0",
"gulp-rename": "^1.2.0",
"gulp-sass": "^4.0.2",
"gulp-util": "^2.2.14",
"gulp-watch": "^5.0.1",
"jshint": "^2.9.6",
"shelljs": "^0.3.0"
},
when run ionic serve --verbose :
[v1] 2019-08-30T10:15:16.695Z ionic:v1-toolkit:lib:gulp Using gulpfile: E:\xx\gulpfile.js
[v1] 2019-08-30T10:15:16.701Z ionic:v1-toolkit:lib:gulp Using gulp: E:\xx\node_modules\@ionic\v1-toolkit\node_modules\gulp\index.js
[v1] 2019-08-30T10:15:19.180Z ionic:v1-toolkit:lib:gulp Loaded gulp tasks: {}
[v1] [17:15:19] Serving directory www
gulpfile.js
gulp.task('ionic:serve:before', gulp.series('default'),
function (done) {
done();
});
Same problem here - I've updated my local gulp to 4.0.2, migrated the gulpfile, but ionic cordova build android is trying to use it's own gulp 3.9.1, which doesn't know how to read the new gulpfile.
Does anyone know if it is at least possible to somehow manually update/hack the @ionic/v1-toolkit to use gulp 4.0.2 instead of 3.9.1?
Edit: I tried directly changing the gulp dependency in package.json of @ionic/v1-toolkit to gulp 4.0.2, but then there are other problems - specifically, @ionic/v1-toolkit seems to use gulp.hasTask which has been removed in gulp 4, if I understand correctly. So the only solution would be to properly update @ionic/v1-toolkit to use gulp 4, which could break some backwards compatibility, I guess.
On Node 12+, build failed because @ionic/v1-toolkit still depends on gulp 3.9 :
> ionic-v1 build
ionic:v1-toolkit:lib:gulp Using gulpfile: <PROJECT>/gulpfile.js +0ms
ionic:v1-toolkit:lib:gulp Using gulp: <PROJECT>/node_modules/@ionic/v1-toolkit/node_modules/gulp/index.js +1ms
Cannot load gulp: ReferenceError: primordials is not defined
It seems that:
A solution is to update dependency of @ionic/v1-toolkit to gulp@^4.0.2
Most helpful comment
Same problem here - I've updated my local gulp to 4.0.2, migrated the gulpfile, but
ionic cordova build androidis trying to use it's own gulp 3.9.1, which doesn't know how to read the new gulpfile.Does anyone know if it is at least possible to somehow manually update/hack the @ionic/v1-toolkit to use gulp 4.0.2 instead of 3.9.1?
Edit: I tried directly changing the gulp dependency in package.json of @ionic/v1-toolkit to gulp 4.0.2, but then there are other problems - specifically, @ionic/v1-toolkit seems to use
gulp.hasTaskwhich has been removed in gulp 4, if I understand correctly. So the only solution would be to properly update @ionic/v1-toolkit to use gulp 4, which could break some backwards compatibility, I guess.