Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: using browserify to import dependencies #1256

Merged
merged 15 commits into from
Dec 17, 2018
Merged

Conversation

jeeyyy
Copy link
Contributor

@jeeyyy jeeyyy commented Nov 22, 2018

This is a developer workflow enhancement PR.

Ability to require external modules has been difficult in Axe.
Previous attempts to require and inject modules into axe global have been not stable, due to having to adapt for various module bundling standards followed by different dependencies.

This PR, circumvents the above problems and introduces a fluent way to require, by embracing browserify.

  • Removed old generate-imports grunt multi task, which was flaky.
  • Introduce npm script - npm run imports-gen which passes dependencies to mount on axe as arguments.
  • axe.imports = { ...myDependencies } is constructed at build time.
  • Deleted copy pasted library css-selecter-parser and changed into as a require dependency.

Closes issue: NA

Reviewer checks

Required fields, to be filled out by PR reviewer(s)

  • Follows the commit message policy, appropriate for next version
  • Has documentation updated, a DU ticket, or requires no documentation change
  • Includes new tests, or was unnecessary
  • Code is reviewed for security by: @WilcoFiers

@jeeyyy jeeyyy requested a review from a team as a code owner November 22, 2018 14:04
@@ -340,6 +329,10 @@ module.exports = function(grunt) {
}
},
run: {
npm_run_imports: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we define this in package.json#scripts instead?

{
  "scripts": {
    "build": "grunt build",
    "prebuild": "npm run imports-gen"
  }
}

This way, we don't get the same confusion we had in #1252/#1250.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this @stephenmathieson, but this required developer documentation update at various places.

Our docs are tied to steps like grunt dev, grunt build and grunt translate. So the only way to trigger any current npm script is via grunt-run, like above.

You concern of what confusion happened in above #1252 etc., will not re-occur as I have already stripped out multiple references to same task and refactored it.

As you can see from most of the chore PR's, once we more to pure npm scripts, it will be easier to update documentation when we have change all of the grunt tasks. So the answer is NO for the time being.

As if I do this change above now, a developer running grunt build will yield different results to npm run build.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That may be true about grunt-run and so on, so I can understand not wanting to take all of that on. As an aside, though, I wouldn't let developer docs stop you from making any changes; we can always update the docs. I'm happy to help with that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of my chore work in axe-core is moving away from grunt to npm scripts. I will make the switch to above recommendation in a different PR when time is right :).

@@ -0,0 +1,109 @@
/* global Promise */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed. Promise is defined in all versions of Node.js we support.

Copy link
Contributor Author

@jeeyyy jeeyyy Nov 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Unfortunately not, our eslint rules ain't happy for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh strange. PR incoming :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This directive can now be removed.

function parseArgsAsRequireMap(args) {
const argMap = {};

if (args.length % 2) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment explaining why this validates arguments.

*/
function createFile(path, content) {
return new Promise((resolve, reject) => {
mkdirp(getDirName(path), err => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing this with make-dir. mkdirp is unmaintained and does not return a Promise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const {dirname:getDirName} = require('path')
const makeDir = require('make-dir')
const {writeFile} = require('fs/promises')

const createFile = (path, content) => makeDir(getDirName(path)).then(() => writeFile(path, content))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am having minimal luck with fs/promises for some reason.
Cheers for the make-dir suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asides fs/promises API is have a stability level 1 & experimental flag.

package.json Outdated
@@ -56,6 +56,7 @@
},
"scripts": {
"api-docs": "jsdoc --configure .jsdoc.json",
"imports-gen": "node ./build/imports-generator --axios 'axios' --doT 'dot' --CssSelectorParser 'css-selector-parser'",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned that if we keep this mapping as CLI flags, the list may become very difficult to maintain in the future.

Why not just add the mapping to ./build/imports-generator.js?

const mapping = [ ['axios','axios'], ['doT', 'dot'], ['CssSelectorParser', 'css-selector-parser'] ]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, as easy as it is to add a mapping to the imports-generator file. I want this to be reminder that we need to update the code-base to allow for fluent import statements, so the more we add here, we shall prioritise the build system changes.

Happy to move it though. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought moved it to mapping...

}

// browserify `lib/core/imports/index.js`
browserify(importsFile).bundle(async (err, result) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure this is going to work in all cases? What about node.js usage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of our tests ensure that, what gets injected into axe.imports is as expected.

I have done some node testing locally. But we will ensure that it works before a release.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you expect we'll "ensure that it works before a release"? Instead of waiting until release-time, can we perform those tests on your branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will discuss with @WilcoFiers.


/**
* Convert arguments to object map of require statement
* @param {Array<String>} args key value pair of arguments
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put an example here? "Key value pair" sounds like an object, but it's an array of strings.

throw new Error('Invalid number of arguments');
}

for (let i = 0; i < args.length; i += 2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments for this loop would be good too, since it has an atypical increment (i += 2) and some magic replacing going on below.

@jeeyyy jeeyyy dismissed marcysutton’s stale review November 27, 2018 10:21

Updated. Review again.

// browserify `lib/core/imports/index.js`
browserify(importsFile).bundle(async (err, result) => {
if (err) {
throw new Error('Cannot browserify axe.imports', err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it makes sense to use "browserify" as a verb 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change here. Leaving as is.

@dylanb
Copy link
Contributor

dylanb commented Nov 30, 2018

Could @marcysutton and/or @stephenmathieson review to make sure their issues have been addressed and then let me know and I'll review?

@stephenmathieson
Copy link
Member

@dylanb I'm waiting on a response for #1256 (comment)

.gitignore Outdated
typings/axe-core/axe-core-tests.js
doc/rule-descriptions.*.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this?

Gruntfile.js Outdated
npm_run_eslint: {
cmd: 'npm',
args: ['run', 'eslint']
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These ESLint changes should probably be in their own PR.

const moduleMap = {
axios: 'axios',
doT: 'dot',
CssSelectorParser: 'css-selector-parser'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer this be in a separate PR too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but I need this PR to land first then.


async function run() {
// generate `axe.imports` content
const fileContent = `
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in favour of dynamically generating this file. Let's just put this file in source control and have this import-generator copy over into tmp.

@jeeyyy
Copy link
Contributor Author

jeeyyy commented Dec 4, 2018

@dylanb - thanks for the comment. I believe @WilcoFiers has a handle on this for review and approvals.

@WilcoFiers
Copy link
Contributor

Looks fine to me. @JKODU can you run this in the Attest extension and in Attest node to make sure this doesn't accidentally break anything?

@jeeyyy
Copy link
Contributor Author

jeeyyy commented Dec 6, 2018

@WilcoFiers

Tested both extensions and node suite. Works 👏

@@ -0,0 +1,109 @@
/* global Promise */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This directive can now be removed.

// browserify `lib/core/imports/index.js`
browserify(importsFile).bundle(async (err, result) => {
if (err) {
throw new Error('Cannot browserify axe.imports', err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts here?

* @param {String} content contents of the file
* @returns {Promise}
*/
function createFile(path, content) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, but I'd still like to see this simplified. Maybe:

const makeDir = require('make-dir')
const fs = require('fs')
const {promisify} = require('util')

const writeFile = promisify(fs.writeFile)

const createFile = (path, content) => makeDir(getDirName(path)).then(() => writeFile(path, content))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Between, this PR and the axe rule generator PR, there is more or less the same createFile fn. Once both are merged. I plan to refactor this into a shared utility fn.

@jeeyyy jeeyyy merged commit eed6589 into develop Dec 17, 2018
@jeeyyy jeeyyy deleted the browserify-imports branch December 17, 2018 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants