diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 851d7ace4c..9e65f65ecc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ As of Dash 1.2, the renderer bundle and its peer dependencies can be packed and 3. `renderer bundles` parses the locked version JSON, copies all the peer dependencies into dash_renderer folder, bundles the renderer assets, and generates an `__init__.py` to map all the resources. There are also a list of helpful `scripts` property defined in `package.json` you might need to do some handy tasks like linting, syntax format with prettier, etc. 4. `renderer digest` computes the content hash of each asset in `dash_renderer` folder, prints out the result in logs, and dumps into a JSON file `digest.json`. Use this when you have a doubt about the current assets in `dash_renderer`, and compare it with previous result in one shot by this command. 5. `renderer build` runs 1, 2, 3, 4 in sequence as a complete build process from scratch. -6. `renderer watch` runs the webpack in watch mode, so any source code change triggers a rebuild. Use this if you are actively updating renderer code and you want to test your changes immediately. +6. `renderer build local` runs the same order as in 5 and also generates source maps for debugging purposes. You also need to install dash-renderer with editable mode: `pip install -e .`. When a change in renderer code doesn't reflect in your browser as expected, this could be: confused bundle generation, caching issue in a browser, python package not in `editable` mode, etc. The new tool reduces the risk of bundle assets by adding the digest to help compare asset changes. diff --git a/dash-renderer/CHANGELOG.md b/dash-renderer/CHANGELOG.md index 1830839ca5..1bbf221264 100644 --- a/dash-renderer/CHANGELOG.md +++ b/dash-renderer/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## Unreleased + +### Fixed +- Reduced about 55% of the dash-renderer packages size on **PyPI** by removing the source maps. To do more advanced debugging, the source maps needs to be generated from source code with `npm run build:local` and pip install in editable mode, i.e. `pip install -e .` [#910](https://github.com/plotly/dash/pull/910) + ## [1.0.1] - 2019-08-27 - Clean all the binary assets in dash-renderer repo, add tool to build all the required bundles from fresh source code to avoid confusion of the assets and improve the release process. [#874](https://github.com/plotly/dash/pull/874) diff --git a/dash-renderer/MANIFEST.in b/dash-renderer/MANIFEST.in index b17522ced4..0c9ca09a82 100644 --- a/dash-renderer/MANIFEST.in +++ b/dash-renderer/MANIFEST.in @@ -1,4 +1,4 @@ include package.json include digest.json include dash_renderer/*.js -include dash_renderer/*.map +exclude dash_renderer/*.map diff --git a/dash-renderer/init.template b/dash-renderer/init.template index 17d90ca57f..c92708ec3c 100644 --- a/dash-renderer/init.template +++ b/dash-renderer/init.template @@ -45,8 +45,6 @@ _js_dist = [ { "relative_package_path": "{}.min.js.map".format(__name__), "dev_package_path": "{}.dev.js.map".format(__name__), - "external_url": "https://unpkg.com/dash-renderer@$version" - "/dash_renderer/dash_renderer.min.js.map", "namespace": "dash_renderer", "dynamic": True, }, diff --git a/dash-renderer/package.json b/dash-renderer/package.json index 549f5961a8..6cf410bd5f 100644 --- a/dash-renderer/package.json +++ b/dash-renderer/package.json @@ -6,8 +6,9 @@ "scripts": { "lint": "./node_modules/.bin/eslint --quiet --fix .", "lint:test": "./node_modules/.bin/eslint .", - "build:js": "webpack --mode development && webpack --mode production", - "build:dev": "webpack --mode development --watch", + "build:js": "webpack --build release", + "build:dev": "webpack --build local", + "build:local": "renderer build local", "build": "renderer build", "start": "webpack-serve ./webpack.serve.config.js", "format": "prettier --config .prettierrc --write \"src/**/*.js\"", diff --git a/dash-renderer/webpack.config.js b/dash-renderer/webpack.config.js index 31069b8eb1..81f1bda7cf 100644 --- a/dash-renderer/webpack.config.js +++ b/dash-renderer/webpack.config.js @@ -1,87 +1,84 @@ const webpack = require('webpack'); +const R = require('ramda'); const path = require('path'); const packagejson = require('./package.json'); - const dashLibraryName = packagejson.name.replace(/-/g, '_'); -module.exports = (env, argv) => { - let mode; - - // if user specified mode flag take that value - if (argv && argv.mode) { - mode = argv.mode; - } - - // else if configuration object is already set (module.exports) use that value - else if (module.exports && module.exports.mode) { - mode = module.exports = mode; - } - - // else take webpack default - else { - mode = 'production'; - } - return { - entry: {main: ['@babel/polyfill', 'whatwg-fetch', './src/index.js']}, - output: { - path: path.resolve(__dirname, dashLibraryName), - filename: - mode === 'development' - ? `${dashLibraryName}.dev.js` - : `${dashLibraryName}.min.js`, - library: dashLibraryName, - libraryTarget: 'window', - }, - devtool: 'source-map', - externals: { - react: 'React', - 'react-dom': 'ReactDOM', - 'plotly.js': 'Plotly', - 'prop-types': 'PropTypes' - }, - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - use: { - loader: 'babel-loader', - }, - }, - { - test: /\.css$/, - use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - }, - ], +const defaultOptions = { + mode: 'development', + devtool: 'none', + entry: { + main: ['@babel/polyfill', 'whatwg-fetch', './src/index.js'], + }, + output: { + path: path.resolve(__dirname, dashLibraryName), + filename: `${dashLibraryName}.dev.js`, + library: dashLibraryName, + libraryTarget: 'window', + }, + externals: { + react: 'React', + 'react-dom': 'ReactDOM', + 'plotly.js': 'Plotly', + 'prop-types': 'PropTypes', + }, + plugins: [], + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', }, - { - test: /\.svg$/, - use: ['@svgr/webpack'] - }, - { - test: /\.txt$/i, - use: 'raw-loader', + }, + { + test: /\.css$/, + use: [ + { + loader: 'style-loader', + }, + { + loader: 'css-loader', + }, + ], + }, + { + test: /\.svg$/, + use: ['@svgr/webpack'], + }, + { + test: /\.txt$/i, + use: 'raw-loader', + }, + ], + }, +}; +module.exports = (_, argv) => { + const devtool = argv.build === 'local' ? 'source-map' : 'none'; + return [ + R.mergeDeepLeft({devtool}, defaultOptions), + R.mergeDeepLeft( + { + devtool: devtool, + mode: 'production', + output: { + filename: `${dashLibraryName}.min.js`, }, - ], - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin( - /(.*)GlobalErrorContainer.react(\.*)/, - function(resource) { - if (mode === 'production') { - resource.request = resource.request.replace( - /GlobalErrorContainer.react/, - 'GlobalErrorContainerPassthrough.react' - ); - } - } - ), - ], - }; + plugins: [ + new webpack.NormalModuleReplacementPlugin( + /(.*)GlobalErrorContainer.react(\.*)/, + function(resource) { + resource.request = resource.request.replace( + /GlobalErrorContainer.react/, + 'GlobalErrorContainerPassthrough.react' + ); + } + ), + ], + }, + defaultOptions + ), + ]; }; diff --git a/dash/development/build_process.py b/dash/development/build_process.py index e1e7565a50..9745dbf8f3 100644 --- a/dash/development/build_process.py +++ b/dash/development/build_process.py @@ -77,10 +77,10 @@ def watch(self): os.system("npm run build:dev") @job("run the whole building process in sequence") - def build(self): + def build(self, build=None): self.clean() self.npm() - self.bundles() + self.bundles(build) self.digest() @job("compute the hash digest for assets") @@ -108,7 +108,7 @@ def digest(self): ) @job("copy and generate the bundles") - def bundles(self): + def bundles(self, build=None): if not os.path.exists(self.build_folder): try: os.makedirs(self.build_folder) @@ -142,9 +142,10 @@ def bundles(self): self._concat(self.build_folder, target), ) - logger.info("run `npm run build:js`") + _script = 'build:dev' if build == 'local' else 'build:js' + logger.info("run `npm run %s`", _script) os.chdir(self.main) - run_command_with_process("npm run build:js") + run_command_with_process("npm run {}".format(_script)) logger.info("generate the `__init__.py` from template and verisons") with open(self._concat(self.main, "init.template")) as fp: