Giter Site home page Giter Site logo

yprox-cli's Introduction

yProx-CLI

CI

A tool for bulk linting and building assets.

Another tool?

Yes, but linting and building a lot of assets is now easier than ever!

Out of the box, yProx-CLI comes with:

  • JavaScript support (+ Buble)
  • CSS and Sass support
  • Rollup support (JavaScript, Vue, GraphQL) for modern apps
  • ESLint for linting JavaScript files
  • Stylelint for linting CSS and Sass support
  • Copy/Paste files
  • Images optimization

yProx-CLI is really useful for us because it allowed us to package all the tools we need in only big package.

We have ~150 WordPress projects and it was really hard to maintain ~25 dev dependencies (for Gulp) for each project. Using yProx-CLI saves us some huge amount of time because:

  • we were able to externalize all those dependencies in one package
  • we were able to externalize the tooling in one package. Before, everything was in a Gulp file configuration

Documentation

Read the documentation.

Development workflow

You need to install dependencies first:

$ yarn

Tests

Tests are located inside the test folder. You can run them with:

$ yarn test

Be sure to always add a test when you are modifying something!

Linting

We use ESlint, the AirBnb preset, the Recommended rules for TypeScript, and Prettier.

You can lint the code with:

$ yarn lint
$ yarn lint --fix # will automatically fix some errors

Contribution

Publishing a new release

  • Open a PR develop to master
  • Merge your pull request with a Merge commit

yprox-cli's People

Contributors

kocal avatar dependabot[bot] avatar dependabot-preview[bot] avatar szepeviktor avatar

Stargazers

Jack avatar Tristan Bessoussa avatar  avatar

Watchers

James Cloos avatar  avatar Leclercq Guillaume avatar Yanick  avatar RomulusED69 avatar Xavier Vallot avatar  avatar  avatar  avatar

yprox-cli's Issues

Remove config from package.json

Only use config from yprox-cli.config.js, also improve options structure if we can.

Don't use YPROX_CLI_IGNORE_CONFIG_FILE or YPROX_CLI_IGNORE_PACKAGE_JSON_FILE env vars anymore.

Merge JS and Rollup handlers

Actually the only "benefit" from using the js handler is that you can easily concat JS files.

  • Remove handler js
  • Rename rollup handler to js
  • Equivalent is to create a .js file and import other files

We can also add a new handler concat.

AppVeyor

Use AppVeyor aside Travis for Windows builds

Travis: add Node.js 10

Since we use yProx-CLI on our wordpress project and they use Node.js 10 (through Scalingo)

Add ConfigGenerator

A bit related to #634

Add a config generator, aside the old plain-object config? We would have access to typings and a easier usage.

const { ConfigGenerator } = require('@yproximite/yprox-cli');

const configGenerator = ConfigGenerator.init()
  .configureAssets('app', (asset) => {
    asset.addRollupEntry('src/yprox-cli.config.js/my-file.js', rollupOptions => {});
    asset.copyFiles(from, to);
    asset.optimizeImages(from, to);
    asset.addSassEntry(...); 
    // ...
  })
  .configureRollup(options => {
     // ...
   })
;

module.exports = configGenerator.generate()

Methods to implement:

  • .addEntry(name, ['...'], {})
  • .addStyleEntry(name, ['...'], {}),
  • .copyFiles(from, to)
  • .optimizeImages(from, to)
  • .configureRollup(rollup => { })
  • .configureESLint(eslint => { })
  • .configurePostCSS(postcss, => {})
  • .configureAutoprefixer(autoprefixer => {});
  • .configureImagesOptimization(options => {});

Add a way to generate both (un)minified JS files

In order to prevent tricks like

concat: `admin${cli.isProduction() ? '.min': '' }.js`,
"scripts": {
    "build": "yarn build:dev && yarn build:prod",
    "build:dev": "yprox-cli build --mode development",
    "build:prod": "yprox-cli build --mode production",
}

fix rollup watch

selection_832

const rollup = require('rollup');
const builtins = require('rollup-plugin-node-builtins');
const nodeResolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const string = require('rollup-plugin-string');
const json = require('rollup-plugin-json');
const globals = require('rollup-plugin-node-globals');
const replace = require('rollup-plugin-replace');
const vue = require('rollup-plugin-vue').default;
const buble = require('rollup-plugin-buble');
const { terser } = require('rollup-plugin-terser');
const log = require('fancy-log');

module.exports = (cli, entry, args) => {
  const rollupOptions = cli.projectOptions.handlers.rollup;

  const getInputOptions = () => {
    const plugins = [];

    plugins.push(builtins());
    if (rollupOptions.nodeResolve !== false) plugins.push(nodeResolve(rollupOptions.nodeResolve));
    if (rollupOptions.commonjs !== false) plugins.push(commonjs(rollupOptions.commonjs));
    if (rollupOptions.string !== false) plugins.push(string(rollupOptions.string));
    if (rollupOptions.json !== false) plugins.push(json(rollupOptions.json));
    plugins.push(globals());
    if (rollupOptions.vue !== false) plugins.push(vue(rollupOptions.vue));
    if (rollupOptions.buble !== false) plugins.push(buble(rollupOptions.buble));

    plugins.push(replace({
      'process.env.NODE_ENV': JSON.stringify(cli.mode),
    }));

    if (cli.mode === 'production') {
      plugins.push(terser(cli.projectOptions.uglify));
    }

    return {
      plugins,
      input: entry.src,
      external: Object.keys(rollupOptions.shims),
    };
  };

  const getOutputOptions = () => ({
    file: `${entry.dest}/${entry.concat}`,
    format: entry.format || 'umd',
    name: entry.name,
    sourcemap: cli.mode === 'production',
    globals: rollupOptions.shims,
  })

  const writeBundle = (bundle) => bundle.write(getOutputOptions());

  const build = () => {
    log.info(`Rollup: start bundling "${entry.src}"`);

    return rollup.rollup(getInputOptions())
      .then(bundle => writeBundle(bundle))
      .catch(err => {
        log.error(err.message, err.loc, err.snippet);
        console.log(err);

        if (!args.watch) {
          process.exit(1);
        }
      });
  };

  const watch = () => {
    const watchOptions = Object.assign({}, getInputOptions(), {
      output: getOutputOptions(),
      watch: {
        chokidar: true,
      },
    });

    const watcher = rollup.watch(watchOptions);

    watcher.on('event', (e) => {
      const { code } = e;

      if (code === 'BUNDLE_START') {
        log.info(`Rollup (watch): start bundling "${entry.src}"`);
      } else if (code === 'BUNDLE_END') {
        log.info(`Rollup (watch): done bundling "${entry.src}"`);
      } else if (['ERROR', 'FATAL'].includes(code)) {
        log.error(`Rollup (watch): something wrong happens`);
        log.error(e);
      }
    });
  };

  return args.watch ? watch() : build();
};

Issue with `--lint` and `--watch` flags

When running build command with both flags, if we have a lint error then we won't watching files.

If we are in watching mode and we have a lint error, then we pass, we should not stop the execution flow.

improve(API): create "resolve" method

Small improvment:

const { resolve } = require('path');

class API {
  resolve(path) {
    return resolve(this.context, path)
  }
}

// ...

const api = new API('/foo/bar');
api.resolve('.') // '/foo/bar'
api.resolve('node_modules') // '/foo/bar/node_modules'

Next major version (3)

Features

  • Configure the tool through the package.json under the key "yprox-cli" (#144)
  • Add API#isProduction() method, it should check for process.env.NODE_ENV === 'production' (#145)
  • Add rollup-plugin-graphql for importing .graphql files as ES5 modules (#147)

Refactoring

  • Rewrite the tool in TypeScript (#138, #150)
  • For the config, tools like autoprefixer, cssnano or optipng should not be under the key handlers. Rollup, sass or css are handlers, but those tools are not. We should do the same as bublé I think (#148)
  • More and small functions, lighten command and handlers from utils methods

Removals

  • webpack handler, I think this was a huge mistake to add it. Yprox-CLI should stay light and simple, we already have Rollup which does the same thing. If you want to use webpack, then use it or use vue-cli/webpack-encore. (#140)
  • Remove rollup-plugin-string (#147)

Misc/Internals

  • Create an UPGRADE-3.0.md file
  • Check if we can configure browserlist (autoprefixer) from package.json and/or .browserslistrc (yes, checked manually)
  • See for writing tests (unit and integration, but it would be nice to remove test-app folder) (#152)
  • Remove the default value {} of path options, in fact it should not be in the options schema
  • If entry's src is not an array, then convert it to an array (#143)
  • Replace gulp-uglify-es by gulp-terser (#146)
  • Named entries { handler: '..', src: ['...'], name: '<name>' }, use the entry's name instead of printing all sources (when bundling) (#149)

Improve filters

  • --filter:handler sass
  • --filter:name "Foo bar"
  • --filter:<attr> "<value">

Plugin system

If we use yProx-CLI only to build some CSS, copy files or optimize images, we probably don't want to install Rollup dependencies :

  • @kocal/rollup-plugin-graphql
  • @types/rollup-plugin-node-resolve
  • rollup-plugin-buble
  • rollup-plugin-commonjs
  • rollup-plugin-json
  • rollup-plugin-node-builtins
  • rollup-plugin-node-globals
  • rollup-plugin-node-resolve
  • rollup-plugin-replace
  • rollup-plugin-terser
  • rollup-plugin-vue

Each handler (css, file, image, js, rollup, sass) will be splited into multiples packages.

Each package will register itself through the API, by using methods like api.getBuilder().add('js', fnThatBuildJavaScript) or api.getLinter().add('js', fnThatLintJavaScript).
The registration will be done by the API, by seeking @yproximite/yprox-cli-handler-* packages in dependencies/devDepenendecies from the package.json of the project.

We will have multiples packages in the same repository, so we will use yarn workspaces:

  • Workspaces are nice, each packages will have their dependencies (and they won't be duplicated)
  • Dependabot is compatible with
  • But semantic-release seems to be not (semantic-release/semantic-release#193) at the moment

Also, it will speed up tests. They became heavy since #226 (but that was necessary).

Trouver un nom de projet

Autre que yProx-cli,

Faire en sorte qu'une fois renommé, yprox-cli continue de fonctionner pour éviter en interne de repasser en masse sur les WP.

A discuter ensemble pour open sourcer.

Improve Sass files linting

Currently, Sass files linting is done in a very bad way:

return `${path.dirname(file)}/**/*.{scss,sass}`.replace(/\\/g, '/');

For an entry with src: ['./src/foo.scss'], it will lint ./src/**/*.{scss,sass} files. Instead, it should lint src/foo.scss and its dependencies, not everything.

To improve this behavior, we can:

  • starts to globify every entries src, to run Stylelint only one time
  • create a dependencies graph, maybe with sass-graph but it seems that custom resolvers are not supported, and I don't know if the file should be syntactically valid :/
  • one we have the dependencies graph, we can run Stylelint on those files

Rework the documentation

  • On documentation index page, in 1/2 sentence, explain what does yProx-cli and what is its difference/advantages compared to other tools.
  • On documentation index page, provide 1 simple example to have a global picture on how easy it is to use it.
  • it minimize -> it minimizes
  • Linting should have its own chapter in the documentation since it's a big "part" in term of features. Explain which tool it's using under the hood.
  • Example -> Examples inside Environment variables and modes
  • Rework this: https://github.com/Yproximite/yProx-cli/blob/master/README.md#L6

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.