I needed to create a new webform on a production site recently. But as a dev, I don't have direct access to the production admin backend; I'm only allowed to push code changes and let the client's team migrate them to prod via drush updb. So I'm supposed to export the webform configuration to code, and deploy it via an update hook, but how?

Because webform nodes are content not configuration, the Features module doesn't help. We generally use the Migrate module with CSVs for content staging, but the thought of exporting arbitrary webform config to CSV gives me the heebie jeebies. The happy medium is node_export, that old-school module that gives a simple UI to export, copy-and-paste, and import a node's configuration across two sites. And using it would work, but would require maintaining its 300 lines of code FOREVER after, just for one silly webform. Shouldn't it be simpler?

I found an even simpler module called webform_share that achieves the same serialization/deserialization webform config in just 200 lines of code. Looking through its source code, the serialization part is quite simple. On the export side, it boils down to this:

$node = node_load(DEV_SITE_NID);

And on the import side, to process the config you've pasted in:

$node = node_load(PROD_SITE_NID);
$node->webform = PASTED_CONFIG;

It dawned on me I can just stick the export part into drush php-eval:

drush ev 'var_export(node_load(DEV_SITE_NID)->webform);'

For the record, the output looks like this.

To import the serialized form onto the prod db, we just create the following update hook in one of our custom modules:

 * Imports the Contact Us webform from development.
 * Implements hook_update_N().
function custommodule_7001() {
  $webform = array( PASTE IN STUFF FROM YOUR EXPORT);
  // clean out exported nids that are hard-coded, apparently

  $node = new stdClass();
  $node->type = 'webform';
  $node->title    = 'Contact Us';
  $node->path = array('alias' => 'contact-us');
  $node->language = LANGUAGE_NONE;
  $node->webform = $webform;

It runs great and requires no extra modules to maintain. We'll be using this trick a lot going forward!