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

Add SCSS Plugins #663

Closed
wants to merge 44 commits into from
Closed

Add SCSS Plugins #663

wants to merge 44 commits into from

Conversation

rayandrew
Copy link

@rayandrew rayandrew commented Jun 17, 2018

Added:

  1. Razzle SCSS Plugin
  2. SCSS Examples
  3. Some unit tests

Add little changes to makeLoaderFinder in razzle-dev-utils.
makeLoaderFinder cannot find loader through object like this:

{
  test: /\.(sa|sc)ss$/,
  use: [
    require.resolve('style-loader'),
	require.resolve('css-loader'),
    ...
  ],
}
const styleLoaderFinder = makeLoaderFinder('style-loader');
config.module.rules.find(styleLoaderFinder); // will return undefined

Not yet implemented:

  • Custom options in SCSS plugins

@rayandrew
Copy link
Author

referencing from issue #662

@rayandrew rayandrew mentioned this pull request Jun 17, 2018
@jaredpalmer
Copy link
Owner

Looks good. But tests didn’t actually run.

@rayandrew
Copy link
Author

hmm, i think there's something missing. I cannot reproduce it on my own

@rayandrew
Copy link
Author

@jaredpalmer, is there any special command to run test?

I have already include test command in scss plugin's package.json

rayandrew and others added 2 commits June 18, 2018 01:01
* preserve the full --inspect= flag as passed to yarn start instead of treating it as a boolean

* update --inspect docs & comments
Copy link
Owner

@jaredpalmer jaredpalmer left a comment

Choose a reason for hiding this comment

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

This is truly awesome! You rock! Just a few nits here and there.

{
"env": {
"jest": true,
"node": true
Copy link
Owner

Choose a reason for hiding this comment

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

Do we need this file in the example?

Copy link
Author

Choose a reason for hiding this comment

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

That's the plugin and I think we need it because eslint screams if i don't put it on eslintrc

@@ -1,3 +1,19 @@
# razzle-plugin-scss

This is just a stub. Not yet implemented.
This package contains a plugin for using SCSS with Razzle
Copy link
Owner

Choose a reason for hiding this comment

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

We should probably document accepted filename endings (.scss, .sass)?

Copy link
Author

Choose a reason for hiding this comment

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

Ah I forgot to put it too. I think it would be nice to put extension in document

## Usage in Razzle Projects

```bash
yarn add razzle-plugin-scss
Copy link
Owner

Choose a reason for hiding this comment

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

--dev

postCssLoaderFinder,
resolveUrlLoaderFinder,
sassLoaderFinder,
styleLoaderFinder,
Copy link
Owner

Choose a reason for hiding this comment

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

Should we document in README what loaderFinders are being exported so people can reuse them?

Copy link
Author

Choose a reason for hiding this comment

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

It would be a good idea! I don't know whether some loaders are reusable at first

"sass-loader": "^7.0.3"
},
"devDependencies": {
"jest": "20.0.4"
Copy link
Owner

Choose a reason for hiding this comment

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

Bump to jest 23

Copy link
Author

Choose a reason for hiding this comment

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

Will upgrade it. But may I ask a question?

"husky": "^0.14.3",
"jest": "^22.4.3",
"lerna": "2.10.1",

razzle lerna package.json still using jest 22.4.3, should I bump it to 23 or stay in 22.4.3?

"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
"postcss-flexbugs-fixes": "^3.3.1",
"razzle": "^2.2.0",
Copy link
Owner

Choose a reason for hiding this comment

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

Razzle is not a dep.

Copy link
Author

Choose a reason for hiding this comment

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

Ah I see, can I make it as dev dependency like typescript-plugin?

"dependencies": {
"autoprefixer": "^8.6.2",
"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
Copy link
Owner

Choose a reason for hiding this comment

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

Use node-sass-chokidar

Copy link
Owner

Choose a reason for hiding this comment

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

it's much less flaky.

Copy link
Author

Choose a reason for hiding this comment

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

I want too, but sass-loader make it as peer dependencies and using node-sass API.

Are you perhaps successfully combine webpack and node-sass-chokidar together?

Copy link
Owner

Choose a reason for hiding this comment

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

Yeah it's just a warning. It works fine. We've used it for almost a year.

Copy link
Author

Choose a reason for hiding this comment

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

Gotcha!


it('should add style-loader', () => {
const rule = config.module.rules.find(styleLoaderFinder);
expect(rule).not.toBeUndefined();
Copy link
Owner

Choose a reason for hiding this comment

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

When I have a lot of tests that have exactly the same structure, I prefer to just keep them in an array and just call forEach on them. Helps stay DRY.

For example:

const devLoaderTests = [{
   name: '...',
   loaderFinder: '...'
}, {
 // ...
},
 {
 // ...
}]


describe('dev', () => {
  devLoaderTests.forEach(item => {
    it(item.name, () => {
     expect(config.module.rules.find(item.loaderFinder).not.toBeUndefined());
    })
  });
});

Copy link
Author

Choose a reason for hiding this comment

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

Ahh sorry for repeating codes. I will fix it!

Copy link
Author

@rayandrew rayandrew Jun 19, 2018

Choose a reason for hiding this comment

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

should I make it recursive?

some tests depends on environment like:

describe('razzle-scss-plugin', () => {
  describe('when creating a web config', () => {
    describe('when environment set to development', () => {

	});

	describe('when environment set to production', () => {

	});
  );

  describe('when creating a node config', () => {
    describe('when environment set to development', () => {

	});

	describe('when environment set to production', () => {

	});
  );
);

or better if I do like this:

describe('razzle-scss-plugin', () => {
  describe('web config on development', () => {

  });

  describe('web config on production', () => {

  });

  describe('node config on development', () => {

  });

  describe('node config on production', () => {

  });
);

what do you think?

Copy link
Author

@rayandrew rayandrew Jun 19, 2018

Choose a reason for hiding this comment

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

here's what I do in mocha + chai for recursive (will change to suitable tests for razzle):

  const template = (strings, ...keys) => (...values) => {
    const dict = values[values.length - 1] || {};
    const result = [strings[0]];
    keys.forEach((key, i) => {
      const value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result
      .join("")
      .replace(/\s+/g, " ")
      .trim();
  },

  const generateTest = (authenticated, credential, templates, tests) => {
    return _.zipWith(templates, tests, (template, test) => {
      if (_.isFunction(template)) {
        it(template({ ...test.props, ...credential }), async () => {
          if (_.isObject(test)) {
            if (_.isUndefined(test.payload)) {
              test.check(
                await authenticated[test.method](
                  module.exports.baseUrl(test.url)
                )
              );
            } else {
              test.check(
                await authenticated[test.method](
                  module.exports.baseUrl(test.url)
                ).send(test.payload)
              );
            }
          }
        });
      } else {
        describe(template.desc({ role: credential.role }), () => {
          return module.exports.generateTest(
            authenticated,
            credential,
            template.test,
            test
          );
        });
      }
    });
const templateTest = [
  template`should ${"should"} get list of users if ${"role"} is logged in`,
  template`should ${"should"} edit users if ${"role"} is logged in`,
  {
    desc: template`details of specific user by ${"role"}`,
    test: [
      template`should ${"should"} get details of specific wrong id of user because resource not found`,
      template`should ${"should"} get details of specific correct id of user`
    ]
  }
];
const authenticatedTest = [{
   credentials: {
    username: "administrator",
    password: "administrator",
    role: "admin"
   },
   tests: [{
     url: "/users",
     method: `get`,
     check: result => {
      expect(result).to.have.status(200);
      expect(result.body).to.have.ownProperty("data");
      expect(result.body.data).to.be.an("array");
      expect(result.body).to.have.all.keys(paginateProps);
     }
    }, {
     props: {
      should: "not"
     },
     url: `/users/${user.id_user}`,
     payload: user,
     method: `patch`,
     check: result => {
      expect(result).to.have.status(403);
      expect(result.body.message).to.equal("Forbidden");
      expect(result.body.name).to.equal("ForbiddenError");
     }
    },
    [{
     props: {
      should: "not"
     },
     url: `/user/${user.wrong_id_user}`,
     method: `get`,
     check: result => {
      expect(result).to.have.status(404);
      expect(result.body.message).to.equal("User not found.");
      expect(result.body.name).to.equal("NotFoundError");
     }
    }, {
     url: `/user/${user.id_user}`,
     method: `get`,
     check: result => {
      expect(result).to.have.status(200);
      expect(result.body).to.be.an("object");
      expect(result.body).to.include.all.keys(userColumns);
     }
    }],
    ...
   ];

and then generate tests like this

 authenticatedTest.forEach(auth => {
   describe(`authenticated role : ${auth.credentials.role}`, () => {
    const authenticated = chai.request.agent(routes);

    before(() =>
     knex.migrate
     .rollback()
     .then(() => knex.migrate.latest())
     .then(() => knex.seed.run())
     .then(() =>
      authenticated
      .post(`${config.get("routePrefix")}/session`)
      .send(auth.credentials)
     )
     .then(res => {
      expect(res).to.have.status(200);
      expect(res.body).to.have.ownProperty("username");
      expect(res.body).to.have.ownProperty("status");
     })
    );

    after(() =>
     authenticated.del(`${config.get("routePrefix")}/session`).then(res => {
      expect(res).to.have.status(200);
      expect(res.body).to.be.an("object");
      expect(res.body.message).to.equal("Logged out successfully.");
     })
    );

    generateTest(authenticated, auth.credentials, templateTest, auth.tests);
  });

what do you think?

@@ -0,0 +1,113 @@
'use strict';

const createConfig = require('razzle/config/createConfig');
Copy link
Owner

Choose a reason for hiding this comment

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

Ignore prior comment. Make razzle a devDep.

expect(rule).toBeUndefined();
});
});
});
Copy link
Owner

Choose a reason for hiding this comment

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

Remove yarn.lock file please. It will mess up yarn module hoisting

@jaredpalmer
Copy link
Owner

So I think our less and postcss plugins are going to share A LOT of code with this. Do we think it makes sense to abstract some of this into a razzle-plugin-style package and then use that the core for each one? That is, the less, sass, postcss plugins would really just be sort of shell packages that pass in some configs, while the workhorse would be the razzle-plugin-style or like razzle-style-utils or whatever we want to call it.

davidnguyen11 and others added 2 commits June 18, 2018 10:25
* added example razzle + react router 3

* Remove yarn.lock

* Fix pkg.json
* Add polka example

Serves as a generic express middleware-compatible server example. (related to jaredpalmer/after.js#77)

* Remove with-polka/setupTests.js

* Remove yarn.lock
@rayandrew
Copy link
Author

rayandrew commented Jun 18, 2018

That will be a great idea! It seems postcss is used too many times for sure.
It will be great to make it reusable for other plugins too.

PS: gonna make some commits tomorrow with the fixes

@rayandrew
Copy link
Author

any thoughts about this @jaredpalmer?

@jaredpalmer
Copy link
Owner

Sorry was at an offsite yesterday. Looking right meow 🐱

Copy link
Owner

@jaredpalmer jaredpalmer left a comment

Choose a reason for hiding this comment

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

Almost there. Going to discuss the configuration API with my team. Will ping with updates shortly

@@ -1,5 +1,7 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
Copy link
Owner

Choose a reason for hiding this comment

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

cool!

@@ -1,11 +1,11 @@
# razzle-plugin-scss

This package contains a plugin for using SCSS with Razzle
This package contains a plugin for using SCSS/SASS with Razzle
Copy link
Owner

Choose a reason for hiding this comment

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

Link to the sass website here?

Copy link
Author

Choose a reason for hiding this comment

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

gotcha!

```js
// default options
const defaultOptions = {
Copy link
Owner

Choose a reason for hiding this comment

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

When i show off options. Show an example of how to use with a simple change and shortest possible snippet. Then below show/describe defaults beneath. It's just overwhelming here.

Copy link
Author

Choose a reason for hiding this comment

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

Better if I just delete it? I have already shown the default options beneath the example

},
plugins: [
PostCssFlexBugFixes,
Copy link
Owner

Choose a reason for hiding this comment

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

Not sure I'm in love with this API. Let me think about this for a few hours and come back with some ideas.

@rayandrew
Copy link
Author

any updates or changes @jaredpalmer?

@jaredpalmer
Copy link
Owner

Reviewing now. Thanks for the ping

@jaredpalmer
Copy link
Owner

If we can fix conflicts will merge.

@rayandrew
Copy link
Author

i think i need to rebase from the new master branch. will soon resolve the conflicts

thank you for your response @jaredpalmer!

@rayandrew
Copy link
Author

resolved the conflict, wanna hear your thoughts @jaredpalmer

@ion-willo
Copy link

any updates @jaredpalmer?

@mzedeler
Copy link

I could use this plugin too.

@zhangking
Copy link

When will the plan be released?

@snaerth
Copy link

snaerth commented Sep 24, 2018

Any news on the release

@willian
Copy link

willian commented Oct 4, 2018

I am interested in using this too.

@nealoke
Copy link

nealoke commented Oct 5, 2018

+1

@snaerth
Copy link

snaerth commented Oct 21, 2018

No news yet. @RayAndrews would it be possible for you to provide a razzle.config.js for scss and css modules?

@jaredpalmer
Copy link
Owner

@crosscompile can you review on Monday?

@jackjocross jackjocross mentioned this pull request Oct 22, 2018
@jackjocross
Copy link
Collaborator

The PR changes LGTM! I agree this will probably share some code with css and postcss plugins but we can probably add an abstraction around those later.

The history in this PR got a little crazy so I pulled out the relevant changes into #786, @RayAndrews let me know if anything is missing from that PR.

@rayandrew
Copy link
Author

rayandrew commented Oct 22, 2018

Looks good to me too!
Maybe we can move discussion for this feature in PR #786 and close this one?

cc: @jaredpalmer @crosscompile

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.