diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..5d69158021a19c3cf2923c0630dfd7509f0dd03e
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,16 @@
+# Mac OS
+.DS_Store
+
+# NPM
+/node_modules
+npm-*
+
+# Testing
+/.nyc_output
+/coverage
+
+# Build
+/.opt-in
+
+# generated translation files
+/translations
diff --git a/.travis.yml b/.travis.yml
index 59e1d15ba92569c05cd41357603636935a74fff3..55dcc33c0bdc6003ceff02e9d360902a915d87e2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,12 +5,14 @@ addons:
     chrome: stable
 node_js:
 - 8
+env:
+  - NODE_ENV=production
 cache:
   directories:
   - node_modules
 install:
-- npm install
-- npm update
+- npm --production=false install
+- npm --production=false update
 before_deploy:
 - npm --no-git-tag-version version 0.1.0-prerelease.$(date +%Y%m%d%H%M%S)
 - git config --global user.email $(git log --pretty=format:"%ae" -n1)
diff --git a/webpack.config.js b/webpack.config.js
index 474427bbe809e71736d8a08aec9008159a12aa3d..393e9dbb44ffe9b25971ad3d7195dd319ad6e977 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -69,8 +69,88 @@ const base = {
     ] : [])
 };
 
-module.exports = (
-    process.env.NODE_ENV === 'production' ?
+module.exports = [
+    // to run editor examples
+    defaultsDeep({}, base, {
+        entry: {
+            lib: ['react', 'react-dom'],
+            gui: './src/playground/index.jsx',
+            blocksonly: './src/playground/blocks-only.jsx',
+            compatibilitytesting: './src/playground/compatibility-testing.jsx',
+            player: './src/playground/player.jsx'
+        },
+        output: {
+            path: path.resolve(__dirname, 'build'),
+            filename: '[name].js'
+        },
+        externals: {
+            React: 'react',
+            ReactDOM: 'react-dom'
+        },
+        module: {
+            rules: base.module.rules.concat([
+                {
+                    test: /\.(svg|png|wav)$/,
+                    loader: 'file-loader',
+                    options: {
+                        outputPath: 'static/assets/'
+                    }
+                }
+            ])
+        },
+        plugins: base.plugins.concat([
+            new webpack.DefinePlugin({
+                'process.env.NODE_ENV': '"' + process.env.NODE_ENV + '"',
+                'process.env.DEBUG': Boolean(process.env.DEBUG)
+            }),
+            new webpack.optimize.CommonsChunkPlugin({
+                name: 'lib',
+                filename: 'lib.min.js'
+            }),
+            new HtmlWebpackPlugin({
+                chunks: ['lib', 'gui'],
+                template: 'src/playground/index.ejs',
+                title: 'Scratch 3.0 GUI'
+            }),
+            new HtmlWebpackPlugin({
+                chunks: ['lib', 'blocksonly'],
+                template: 'src/playground/index.ejs',
+                filename: 'blocks-only.html',
+                title: 'Scratch 3.0 GUI: Blocks Only Example'
+            }),
+            new HtmlWebpackPlugin({
+                chunks: ['lib', 'compatibilitytesting'],
+                template: 'src/playground/index.ejs',
+                filename: 'compatibility-testing.html',
+                title: 'Scratch 3.0 GUI: Compatibility Testing'
+            }),
+            new HtmlWebpackPlugin({
+                chunks: ['lib', 'player'],
+                template: 'src/playground/index.ejs',
+                filename: 'player.html',
+                title: 'Scratch 3.0 GUI: Player Example'
+            }),
+            new CopyWebpackPlugin([{
+                from: 'static',
+                to: 'static'
+            }]),
+            new CopyWebpackPlugin([{
+                from: 'node_modules/scratch-blocks/media',
+                to: 'static/blocks-media'
+            }]),
+            new CopyWebpackPlugin([{
+                from: 'extensions/**',
+                to: 'static',
+                context: 'src/examples'
+            }]),
+            new CopyWebpackPlugin([{
+                from: 'extension-worker.{js,js.map}',
+                context: 'node_modules/scratch-vm/dist/web'
+            }])
+        ])
+    })
+].concat(
+    process.env.NODE_ENV === 'production' ? (
         // export as library
         defaultsDeep({}, base, {
             target: 'web',
@@ -107,84 +187,5 @@ module.exports = (
                     context: 'node_modules/scratch-vm/dist/web'
                 }])
             ])
-        }) :
-        // to run editor examples
-        defaultsDeep({}, base, {
-            entry: {
-                lib: ['react', 'react-dom'],
-                gui: './src/playground/index.jsx',
-                blocksonly: './src/playground/blocks-only.jsx',
-                compatibilitytesting: './src/playground/compatibility-testing.jsx',
-                player: './src/playground/player.jsx'
-            },
-            output: {
-                path: path.resolve(__dirname, 'build'),
-                filename: '[name].js'
-            },
-            externals: {
-                React: 'react',
-                ReactDOM: 'react-dom'
-            },
-            module: {
-                rules: base.module.rules.concat([
-                    {
-                        test: /\.(svg|png|wav)$/,
-                        loader: 'file-loader',
-                        options: {
-                            outputPath: 'static/assets/'
-                        }
-                    }
-                ])
-            },
-            plugins: base.plugins.concat([
-                new webpack.DefinePlugin({
-                    'process.env.NODE_ENV': '"' + process.env.NODE_ENV + '"',
-                    'process.env.DEBUG': Boolean(process.env.DEBUG)
-                }),
-                new webpack.optimize.CommonsChunkPlugin({
-                    name: 'lib',
-                    filename: 'lib.min.js'
-                }),
-                new HtmlWebpackPlugin({
-                    chunks: ['lib', 'gui'],
-                    template: 'src/playground/index.ejs',
-                    title: 'Scratch 3.0 GUI'
-                }),
-                new HtmlWebpackPlugin({
-                    chunks: ['lib', 'blocksonly'],
-                    template: 'src/playground/index.ejs',
-                    filename: 'blocks-only.html',
-                    title: 'Scratch 3.0 GUI: Blocks Only Example'
-                }),
-                new HtmlWebpackPlugin({
-                    chunks: ['lib', 'compatibilitytesting'],
-                    template: 'src/playground/index.ejs',
-                    filename: 'compatibility-testing.html',
-                    title: 'Scratch 3.0 GUI: Compatibility Testing'
-                }),
-                new HtmlWebpackPlugin({
-                    chunks: ['lib', 'player'],
-                    template: 'src/playground/index.ejs',
-                    filename: 'player.html',
-                    title: 'Scratch 3.0 GUI: Player Example'
-                }),
-                new CopyWebpackPlugin([{
-                    from: 'static',
-                    to: 'static'
-                }]),
-                new CopyWebpackPlugin([{
-                    from: 'node_modules/scratch-blocks/media',
-                    to: 'static/blocks-media'
-                }]),
-                new CopyWebpackPlugin([{
-                    from: 'extensions/**',
-                    to: 'static',
-                    context: 'src/examples'
-                }]),
-                new CopyWebpackPlugin([{
-                    from: 'extension-worker.{js,js.map}',
-                    context: 'node_modules/scratch-vm/dist/web'
-                }])
-            ])
-        })
+        })) : []
 );