Giter Site home page Giter Site logo

yahooarchive / mendel Goto Github PK

View Code? Open in Web Editor NEW
87.0 16.0 25.0 1.96 MB

A build toolchain for experimentation on isomorphic web applications with tree-inheritance and multivariate support.

License: MIT License

JavaScript 99.80% Shell 0.10% CSS 0.10%
build-tool javascript ab-testing web

mendel's Introduction

Mendel

Mendel is a framework for building and serving client side JavaScript bundles for A/B testing experiments in web applications.

It is meant to be simple and easy to use on a daily basis. It works very well for small applications and small teams, but also scale for complex use cases that large applications or larger teams might need.

Example scenario of application A/B testing
+-------------------------------------------------------------------------+
| Shopping cart application                                               |
+------------------------------+--------------------+---------------------+
| 90% of users                 | 5% of users        | 5% of users         |
+-------------------------------------------------------------------------+
| Base experience              | Experiment A       | Experiment B        |
+-------------------------------------------------------------------------+
| By default cart is a link    | Live shopping cart | Live shopping cart  |
| in the horizontal navigation | as a sidebar       | floating and docked |
| menu with counter for number |                    | to the bottom of    |
| of items                     |                    | the page            |
+------------------------------+--------------------+---------------------+

Mendel supports:

  • JavaScript bundle generation (similar to Webpack/Browserify) for each variation/experiment/bucket
  • Isomorphic applications (a.k.a. server side rendering, such as ReactDOMServer or Ember Fastboot)
  • Multivariate testing and/or Multilayer experimentation
  • Variation/experiment/bucket inheritance that enables code-reuse across different experiments.

Mendel does not support:

  • Experiment resolution: Mendel does not provide random assignment of users into experiments
  • Experiments measurement: Mendel does not provide a way to track performance of experiments based on user actions

Both of the above are covered by existing open source tools, such as PlanOut, Open Web Analytics, Piwik and many others.

Advantages of using Mendel

Mendel is built on top of solid design principles and is hardened by years of using the same strategy inside Yahoo, from teams ranging from 3 to 30+ developers contributing daily to large applications. Here are a few of the advantages of using Mendel:

  • Maintainability: All variation/experimentation code is organized and compiled in a way to be immediately disposable, impose no maintenance overhead, and be very easy to debug and analyze.
  • Performance: Server side resolution is synchronous and fast, and client side code will have no payload overhead.
  • Security: Bundle URL and client-side compiled code does not contain variation/experiment information. Only the packages that are absolutely needed are included in the bundle.

Mendel also has a clear development flow. All other experimentation we could find lacked built in support for a smooth development workflow. In Mendel, fast development cycles are a first-class citizen.

How to use Mendel

Mendel uses files to create differences for each experiment you want to run for your users. With Mendel you don't create conditionals such as if(myExperimentRunning) { /* do something different */ }. You just copy the file you need to be slightly different and change your code.

For example, let's say your application has a controllers directory and a views directory, and for a given experiment you will change how display ads are rendered. You then create the following structure in addition to your application code.

bash> tree
...
├── experiments
│   └── new_ad_format
│       ├── controllers
│       │   └── sidebar.js
│       └── views
│           └── ads.js
...

Next, you add the experiment to your configuration. Each experiment is called a "variation" in Mendel, and each variation is a list of folders. Here is the newly added new_ad_format variation:

variationsdir: experiments
variations:
  new_ad_on_sidebar: ## experiment id is inferred from this key
    - new_ad_format  ## directory name (if not same as id)

That's it, with two simple steps, you now have have an experiment ready to run. The default code is usually called base and does not need to be declared. Mendel will then generate bundles for each of your variations.

File system resolution

To understand which files you need to create is very straightforward. Mendel just merges the directory tree in runtime. The resulting tree is not written to disk, but the following diagram explains how your files will be combined for a given experiment:

Bundle "base"                                          Bundle "new_add_format"
       ^                                                      ^
       |                resolution direction                  |
       |      ----------------------------------------->      |

src/                       experiments/new_ad_format/  resolved/new_ad_format/
├── controllers            ├── controllers             ├── controllers
│   ├── main.js            │   │                       │   ├── main.js
│   ├── settings.js        │   │                       │   ├── settings.js
│   └── sidebar.js -----> X│   └── sidebar.js ------------>└── sidebar.js **
├── main_bindle.js         │                           ├── main_bindle.js
├── vendor                 │                           ├── vendor
│   ├── calendar.js        │                           │   ├── calendar.js
│   ├── ember.js           │                           │   ├── ember.js
│   ├── jquery.js          │                           │   ├── jquery.js
│   └── react.js           │                           │   └── react.js
└── views                  └── views                   └── views
    ├── admin.js               │                           ├── admin.js
    ├── ads.js -------------> X└── ads.js ---------------->├── ads.js **
    ├── list-item.js                                       ├── list-item.js
    ├── list.js                                            ├── list.js
    ├── login.js                                           ├── login.js
    ├── new_item.js                                        ├── new_item.js
    └── sidebar_item.js                                    └── sidebar_item.js

** Files marked with ** in the "resolved" tree are used from
the "experiments/new_ad_format/" tree, all other files are used
from "src/" tree.

Stability and Roadmap

The way Mendel experiments are built has been quite stable since mid 2014, and Mendel implementation just improves how it is compiled and adds several features, like multi-layer. Mendel 1.x can be considered stable and is used by production applications at Yahoo. We are also building Mendel 2.x, in which experiment/variations creation will be exactly the same, production middleware API is also considered stable and only file configuration format and development middleware will have breaking changes in 2.0.

Since documentation is still short of ideal, we recommend you start with the "examples" directory. It is a sample application and there is a small Readme file to get you started.

Why is is Mendel so different?

Mendel is the result of extensive research done by Yahoo on how to achieve not only the aforementioned performance goals, but also on how to effectively address development across large teams. We found that conditionals in the code base resulted in experiments which were hard to dispose of after they had run their course, which led to technical debt and poor performance in our code bases.

The main goal for Mendel is to be sustainable. Sustainability comes from being able to test the experiments correctly, keeping experiments up-to-date with our "base/master/default" application code, and keeping front-end performance unchanged throughout experimentation and adoption of experiment results. There is a full design document available if you are curious about the details.

Why is it called "Mendel"?

Gregor Mendel is considered one of the pioneers in genetics. His famous experiments include identifying phenotypes such as seed shape, flower color, seed coat tint, pod shape, unripe pod color, flower location, and plant height on different breeds of pea plants. We find that in many ways, we are doing similar experiments with our software applications. We want to know what "application phenotypes" will be most fitting for the relationship between our products and our users, hence the homage to Gregor Mendel.

Developing Mendel and Contributions

Mendel is a monorepo. In order to develop for Mendel you will need to create a lot of npm links. To make it easier, we created a small script. You can run npm run linkall to link all packages to your node installation and cross-link all Mendel packages that depend on each other. This will also run npm install in all places that you need to.

Mendel follows Browserify's plugin pattern and NPM small packages style. Whitespace conventions are on .editorconfig file, please use editor config plugin for your code editor.

We also have some test documentation in case you want to make a pull request.

License

Mendel is MIT licensed.

mendel's People

Contributors

anuragdamle avatar azu avatar digitaloptgroup avatar gomezd avatar irae avatar jamesalley avatar juandopazo avatar kluzny avatar muralikr avatar neeleshmb avatar stephanwlee avatar tufandevrim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mendel's Issues

Custom resolvers

Hey @irae @stephanwlee! What do you think about the possibility of supporting custom resolvers? In particular, for directories. For example, let's say I want to support require('foo/bar') and have foo resolve to `'./foo1/foo2/foo3' before resolving variations. Would this make sense? How hard do you think it would be to implement?

Development Middleware should not crash while deamon is booting

I am trying to use mendel-v2 with Node Foreman which is a neat process manager that will make a lot of sense for Mendel v2. But development middleware expects not only the process to be running, but to have finished a number of build steps. Here is what I got:

screen shot 2017-03-07 at 7 28 22 pm

Here is the animated version: https://asciinema.org/a/3u30lg9wdtgfbf9besovtqfuq

I had to modify a file in another window so the application would boot.

I think Mendel should have a way of waiting for this async process. Something should be available as soon as the pipeline process starts and the client should be able to detect it.

Mendel Daemon should watch .mendelrc or package.json and soft restart

Here are the two main use cases:

  1. When a new variation is created, mendel-daemon should pickup the new variation.
  2. When a variation is deleted, we should stop watching the files and directories and also don't serve the variation anymore

Additional low priority cases:

  • Adding plugins
  • Adding bundles
  • Misc configuration changes

Faster dependency resolving

It is found to be a bottleneck according to analytics in a large application.

Make it faster which can be done by caching result of fs.stat which is only used to figure out if file exists or not. The cache will have to be invalidated appropriately when fs changes.

A naive cache can be a problem and we may have to design/devise a better way to make this faster; perhaps "bisource resolving" (it is needed for virtual entries) is the problem.

Cannot run full-example in production mode

After 503b84f commit, we cannot run full-example in production env anymore. It is always throwing following error.

$ DEBUG=* npm run build
// All mendel debug logs goes here
  mendel:config   ignores: [],
  mendel:config   noout: false,
  mendel:config   support: '' } +81ms
  mendel:deps:49087 Online +0ms
  mendel:transforms:49085 Online +0ms
  mendel:deps:49088 Online +0ms
  mendel:daemon Initializing for environment: production +0ms
  mendel:pipeline:production working +6ms
Please, use --outlet only when you have another mendel process running on --watch mode.
exit 1
  mendel:daemon Instructed to force exit +16ms
  mendel:transforms:49084 Gracefully exited +80ms
  mendel:transforms:49083 Gracefully exited +86ms
  mendel:transforms:49085 Gracefully exited +66ms
  mendel:transforms:49086 Gracefully exited +55ms
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `NODE_ENV=production mendel`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/muralikr/.npm/_logs/2017-06-02T18_20_57_065Z-debug.log

Migrate from `linkall.js` to `learna` for monorepo menagement

When we started mendel, Learna only had fixed mode and --independent was under heavy development.

Now that learna is stable, we should migrate to that.

Here is my expectation of sub-tasks:

  • mendel-pipeline should have no CLI logic, we should have mendel-cli for that
  • mendel-pipeline to be published as mendel-pipeline and mendel should just be a proxy to mendel-cli
  • split tests into their own package projects
  • migrate to learna

Fault Tolerance

If a file is saved with, say, an undefined variable in it, it will cause the daemon to exit. It's pretty routine to write code, save, and repeat several times before looking at the result in the browser, so this failure can occur frequently.

It would be nice if the daemon could restart itself. Of course, if the error is still present it will fail again, and we don't want it to just endlessly start/stop.

Maybe we could play a chime, beep, or even execute 'say "Daemon stopped. Will attempt to restart in one minute."' which in mac os terminal will make a verbal announcement. Then at least the problem of "keeping an eye on the daemon" would be mitigated.

Different files that yield same `normalizedId` collisions are not detected, production issues

Sometimes, Mendel is resolving files in weird behavior. Although the problem is on my code, it is super hard to track and I only catch this in my CI environment. Here is a summary of the issue:

That's a redacted version of my actual repository.

src/client/base/selectors/
├──...
├── network
│   ├── index.js
│   └── ...
├── network.js
└── ...

Internally mendel represent both of those files with the same normalizedId of selectors/network.
In fact, my code reads require('../selectors/network').

The problem is worst because in development, it is inconsistent. For some developers it will give selectors/network/index.js and it will give selectors/network.js for others.

In production middleware it seems to be 100% consistent to selectors/network.js.

This behavior is not necessarily wrong by mendel. It is doing whatever it is capable of with a tough situation. Nevertheless, I think my compiled bundle could instead, at least in development, throw a meaningful invariant error, since I should not be doing this in my repository anyway.

Sourcemap support

Currently, source maps are roughly accounted for but are not tested/well-implemented. We need this for developer productivity.

Daemon process throws errors for 3rd party transforms

After recent changes to https://github.com/yahoo/mendel/blob/master/packages/mendel-config/src/transform-config.js file, daemon is throwing errors at this line: https://github.com/yahoo/mendel/blob/master/packages/mendel-pipeline/src/transformer/worker.js#L18

[Pipeline] "IndependentSourceTransform" errored:
Errored while transforming ./src/components/body.jsx: Transform foo-bar is incompatible with Mendel.
Error: Transform foo-bar is incompatible with Mendel.
    at promise.then.then (/Users/user1/mendel/packages/mendel-pipeline/src/transformer/worker.js:18:31)
    at process._tickCallback (internal/process/next_tick.js:103:7)

Expected plugin type: function
Actual plugin type: object

As of now, full-example has json-parse transform which is not used. Hence, we couldn't catch this error during testing.

@irae @stephanwlee

[Documentation] Pipeline

Prepare an appendix that captures:

  • Pre: watcher + FS read
  • Independent Source Transform
  • Graph Source Transform
    • [WIP] Virtual Entries
  • Generator
  • Outlet

SSR is not working in full-example when using a fresh clone of the repo

Looks like resolver is trying to require from "base" folder instead of "build/server".

To reproduce this with a fresh clone:

  1. clone the repo
  2. go to full example
  3. npm install
  4. npm run build && npm run production

To reproduce with a current repo:

  1. unlink all modules
  2. git clean -dfx
  3. go to full example
  4. npm install
  5. npm run build && npm run production

mendel-daemon is terminated because of memory issue

Randomly, daemon process is quit with following error message. It doesn't seem to be related to sync or any file changes. Sometimes, it is terminated right after startup. This has been happening frequently with latest package updates.

<--- Last few GCs --->
 1537981 ms: Scavenge 733.7 (1434.6) -> 733.6 (1434.6) MB, 2.7 / 0 ms [allocation failure].
 1537984 ms: Scavenge 733.9 (1434.6) -> 733.8 (1434.6) MB, 2.6 / 0 ms [allocation failure].
 1537987 ms: Scavenge 733.9 (1434.6) -> 733.8 (1434.6) MB, 3.0 / 0 ms [allocation failure].
 1537990 ms: Scavenge 734.0 (1434.6) -> 734.0 (1434.6) MB, 2.5 / 0 ms [allocation failure].
 1537993 ms: Scavenge 734.1 (1434.6) -> 734.1 (1434.6) MB, 2.6 / 0 ms [allocation failure].
<--- JS stacktrace --->
Cannot get stack trace in GC.
FATAL ERROR: Scavenger: semi-space copy
 Allocation failed - process out of memory
sh: line 1: 63295 Abort trap: 6           mendel --watch

Create CLI or tool for generating mendelrc

Mendelrc can be cumbersome to generate. We want to assist users with a good CLI or a webpage.

Invest some time to create a tool like protractor's or karma's or a webpage with bunch of explanation of what each line specifies.

Assigning experiments

I am intrigued by this project and it could be an awesome fit for me. Is the idea that mendel would generate multiple bundles and I can then deal with the logic of what bundle gets served to which user or is that figured into the library too?

Manifest validation needed

Making a manifest is hard enough, without validation is super hard for someone not familiar with mendel internals.

For instance, there is a "outlet" requirement on the "bundle". If you don't match exactly with an existing outlet plugin by id you will get an error deep down on inside the compiler chain. Instead we should warn at boot of the pipeline.

Al required fields should be there, al folders should exist, all references by ID should validate and all modules should be loaded successfully before we start mendel. I think having validation will pay off in the long run better than having a installation script, since people start projects simple and add stuff as they progress.

Most tests failing or invalid

Many tests are running against mendel-browserify or other deprecated modules. Need to port all tests to mendel-pipeline or other appropriate packages, maybe write even more tests.

Support PostCSS plugin for mendel-outlet-css

Tiny problem is the node_modules will be relative to .mendelrc or cwd whereas plugin leaves somewhere else. We may need the global treatment of such plugin paths for all configurations.

In other words, plugin should be a reserved word for a configuration that maps to a relative path.

CSS File that only exists on variation is being picked up by base variation in production build

When using wildcards like /css/*.css on .mendelrc, if a CSS file exists only on a variation and not on base, the base bucket for production build is picking up the file that it shouldn't.

How to reproduce in details:

If I have the following example:

    src/client
    ├── base
    │   └── css
    │       └── activity.css
    └── variations
        └── new-card
            └── css
                ├── activity-addon.css
                └── activity.css

variations/new-card/css/activity-addon.css picked up by base even tho there should be no new-card files being used.

Temporary workaround

Currently I am able to use Mendel by creating a dummy file

    src/client
    ├── base
    │   └── css
    │       └── activity.css
    │       └── activity-addon.css
    └── variations
        └── new-card
            └── css
                ├── activity-addon.css
                └── activity.css

Where:

  • base/css/activity-addon.css is empty

Base variation will now show correct styles.

global is not defined error running full-example from fresh repo clone

When I run the full-example, in production mode, I get Uncaught ReferenceError: global is not defined in the browser. I saw recent discussion around this and it looks like global.foo was added to footer.js as a test case and that mendel added a default shim for global with c97a12e. But maybe I'm seeing that wrong and need to add it manually somewhere?

Mendel and Webpack

Hi,

Thank you for open sourcing Mendel.

I saw in your GitHub docs that you used Browserify for Mendel's implementation because it was more extensible and Webpack wasn't popular (or didn't exist) at the time.

We have a lot of commitment to Webpack and wonder whether you are considering a possible future implementation with Webpack?

Thanks,
Ashley.

JS File that only exists on variation should be picked up

If my variation has a new require, Mendel is failing to pick it up right away. If I create a dummy file on my base variation, it starts working again.

How to reproduce in details:

If I have the following example:

    src/client
    ├── base
    │   └── actions
    │       └── activity.js
    └── variations
        └── new-card
            ├── activity-addon.js
            └── activity.js

Where:

  • base/actions/activity.js has no depencencies.
  • variations/new-card/activity.js has require('./activity-addon')

variations/new-card/activity-addon.js is never picked up on my variation and I get criptic errors, similar to what I would get if file didn't exists.

Workaround

Currently I am able to use Mendel by creating a dummy file

    src/client
    ├── base
    │   ├── activity-addon.js
    │   └── actions
    │       └── activity.js
    └── variations
        └── new-card
            ├── activity-addon.js
            └── activity.js

Where:

  • base/actions/activity.js has no depencencies.
  • base/actions/activity-addon.js is empty file
  • variations/new-card/activity.js has `require('./activity-addon')

variations/new-card/activity-addon.js now works.

npm link all unable to link specific package mendel-full-example

Having some issues run the master npm run linkall and npm unit test see below:

In general should I expect a green build?

npm run linkall
........
local install mendel-full-example ...
npm ERR! Darwin 16.1.0
npm ERR! argv "/Users/kyle/.nvm/versions/node/v5.0.0/bin/node" "/Users/kyle/.nvm/versions/node/v5.0.0/bin/npm" "install"
npm ERR! node v5.0.0
npm ERR! npm v3.3.6
npm ERR! code E404

npm ERR! 404 Registry returned 404 for GET on https://registry.npmjs.org/karma-mendel
npm ERR! 404
npm ERR! 404 'karma-mendel' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 It was specified as a dependency of 'mendel-full-example'
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/kyle/Development/mendel/examples/full-example/npm-debug.log
local install mendel-full-example ...

npm-debug.log.txt

I think this is causing my npm test to fail as well:

npm run unit
.....
test/tree-hash-walker.js ............................ 15/15
test/tree-serializer.js ............................... 9/9
test/tree-variation-walker-server.js .................. 3/3
test/tree-variation-walker.js ......................... 9/9
test/tree-walker.js ................................... 7/7
test/trees.js ....................................... 15/15
Bail out! # should create manifest but failed

npm ERR! Darwin 16.1.0
npm ERR! argv "/Users/kyle/.nvm/versions/node/v5.0.0/bin/node" "/Users/kyle/.nvm/versions/node/v5.0.0/bin/npm" "run" "unit"
npm ERR! node v5.0.0
npm ERR! npm v3.3.6
npm ERR! code ELIFECYCLE
npm ERR! mendel-monorepo@ unit: DEBUG='' tap test/*.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the mendel-monorepo@ unit script 'DEBUG='' tap test/.js'.
npm ERR! This is most likely a problem with the mendel-monorepo package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! DEBUG='' tap test/
.js
npm ERR! You can get their info via:
npm ERR! npm owner ls mendel-monorepo
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/kyle/Development/mendel/npm-debug.log

npm-debug.log.txt

Pickup new node_modules/ when they are installed

During development, sometimes you git pull changes and need to install a new package. I am not proposing Mendel should install the packages, but I think we should track the dependencies.

IIRC, when filesystem watcher scans folders, we don't wildcard watch for node_modules for performance reasons. But we do watch every file we require. I am thinking to fix this, we just need to watch for new node_modules/ we know are missing.

For instance, this is the proposed workflow:

  1. Git pull something, a new file or existing file within variational or base folder requires a new dependency foo.

  2. Dependency foo is not found

    2.1. Currently I think we do not watch for the dependency foo.
    2.2. Suggesting we add foo to a list of dependencies we are looking for and watch node_modules/

  3. User installs foo manually (or maybe they have a grunt task for it).

    3.1. Currently user needs to stop daemon and start again
    3.2. Suggesting we get events on node_modules folder, if it matches array of missing dependencies (in example array is ['foo']) we then require the entry and start watching for changes.

Documentation and Discussion

Hi,

Thanks for sharing Mendel, it sounds very interesting. I heard about it in a podcast and they mentioned new documentation. I wonder when that may be coming?

Also, it is hard to find any discussion of Mendel, reviews and comments, in the web. Is this a result of my first point above or limited exposure?

Cheers,
Ashley.

[meta] Improve full-example restart

In case we detect all mendel modules are npm linkd in full example, npm run daemon should restart when anything inside packages/*mendel* changes. This would help a great deal debugging mendel itself using full-example.

Client Sync operation takes min. 30 seconds

In watch mode: whenever developer modifies any file, client has to sync with daemon process. As of now, sync takes min. 30 seconds. This is impacting developer productivity.

We should reduce this delay as much as possible.

Research / Develop plugin for variational images

Here is an useful scenario Mendel could cover: We already have variational CSS and JS, and some variations might include images to change as well. Right now the only way to setup an app environment and have variational images is as follows:

  1. Have some sort of pipeline for image compression and cache busting outside of mendel
  2. Create different images by name, maybe even use variation folder names to create different images
  3. Deploy all images to CDN, use some sort of pipeline tool to pre-process JS files before adding them to JS/CSS. Different variations can point to different images/assets.

It would be great to just have Mendel handle this complexity the same way it handles JS:

  • Add image plugin to have variational images, maybe it is more than one plugin, one for CSS other for JS
  • Use mendel manifest somehow to reference those images, so in production we get multilayer images and the mendel consistent hash algorithm on the URL.
  • CDN reverse proxy (just like mendel already does for JS) with high expiration headers.

There is a lot of benefits from this approach:

  • Clear mental model from variations applied to assets too
  • Mendel becomes a single tool you can write quality production apps
  • No need to duplicate a JS or CSS file on a variation just because of image change, therefore faster development cycle
  • Future potential: manifest diff can show variations to images (we don't have a tool for that yet, but it could be cool to visualize it)

There is one additional complication this needs to solve: How do we reference/get/replace images from CSS and JS? Should we do something similar to bundle splitting for lazy loading? Should we provide a "require" module on JS that calls a method and gets the paths. What about CSS?

Generator/Outlet for CSS

CSS bundle needs to be handled as part of Mendel.
Since CSS3 (without any preprocessors) cannot have dep graph like JS, it will go through different set of "transforms" and config and we need to validate that it works with Mendel v2.

Moreover, it needs to be compatible with PostCSS.

Cleanup .entries vs. .options.entries in bundle config

In bundle object, we current have
config.entries vs. config.options.entries which mean totally two different things:

  • former: describes modules associated with a bundle
  • latter: describe entry or entrance to an application (entry in browserify sense; we will execute this module as we bootstrap)

Those two are extremely confusing and we have to clean this up (generators and outlets will need to change appropriately).

Components with Cyclic dependency breaks production

With [email protected], we are reading component files from build/server folder. In one way, it is good since we don't have to transpile these files anymore in runtime. Earlier, we were reading es6 files from full-example folder for server side rendering.

With this change, we don't seem to support cyclic dependency anymore. I have created a test commit to create this behavior inside full-example. I am able to launch this app in development mode. In production, it always throws error.

TypeError: Foo.getLogString is not a function

Middleware client should not crash app when client code is invalid

I was during my normal developer flow, and I got a git conflict.

Git conflicts are pretty common workflow and they often break syntax. Here is what I got back:

9:20:51 AM web.1     |  [nodemon] starting `node src/server.js`
9:20:52 AM web.1     |  /Users/irae/code/consider/web-fe/fixtures/query/clauses.js:17
9:20:52 AM web.1     |  <<<<<<< HEAD
9:20:52 AM web.1     |  ^^
9:20:52 AM web.1     |  SyntaxError: Unexpected token <<
9:20:52 AM web.1     |      at Object.exports.runInThisContext (vm.js:76:16)
9:20:52 AM web.1     |      at Module._compile (module.js:542:28)
9:20:52 AM web.1     |      at Object.Module._extensions..js (module.js:579:10)
9:20:52 AM web.1     |      at Module.load (module.js:487:32)
9:20:52 AM web.1     |      at tryModuleLoad (module.js:446:12)
9:20:52 AM web.1     |      at Function.Module._load (module.js:438:3)
9:20:52 AM web.1     |      at Module.require (module.js:497:17)
9:20:52 AM web.1     |      at require (internal/module.js:20:19)
9:20:52 AM web.1     |      at Object.<anonymous> (/Users/irae/code/consider/web-fe/src/views/fixture-loader.js:4:50)
9:20:52 AM web.1     |      at Module._compile (module.js:570:32)
9:20:52 AM web.1     |      at Object.Module._extensions..js (module.js:579:10)
9:20:52 AM web.1     |      at Module.load (module.js:487:32)
9:20:52 AM web.1     |      at tryModuleLoad (module.js:446:12)
9:20:52 AM web.1     |      at Function.Module._load (module.js:438:3)
9:20:52 AM web.1     |      at Module.require (module.js:497:17)
9:20:52 AM web.1     |      at require (internal/module.js:20:19)
9:20:52 AM web.1     |  [nodemon] app crashed - waiting for file changes before starting...

I fully agree that we should log this error, and the stack is correct. But the last line shows that my server crashed with this change, which is something I would not expect to happen. It is not that bad, but workflow could be improved by console.error with colors and recovering transparently.

Fix Configuration for Bundle/Outlet

In some bundle, you want to bundle everything of certain type without walking dependency graph (CSS?) However, since a bundle contains single type (unless exception comes up; let's see what happens then), type should/does declare what kind of outlet is appropriate. It seems like bundle should contain type information or entry "files".

Also, entries in bundles have a path. Should it be relative path from .mendelrc or should it be relative path from base variation directory?

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.