├── .gitignore
├── LICENSE
├── README.md
├── config
├── plugin
│ ├── babel.js
│ ├── eslint.js
│ ├── paths.js
│ └── webpack.js
└── webview
│ ├── babel.js
│ ├── env.js
│ ├── eslint.js
│ ├── paths.js
│ ├── polyfills.js
│ ├── webpack-dev-server.js
│ ├── webpack-dev.js
│ └── webpack-prod.js
├── docs
└── index.html
├── headers
└── parsed
│ └── .gitkeep
├── logo.svg
├── package.json
├── scripts
├── build.js
├── parse-headers.js
├── plugin
│ ├── build.js
│ └── bundle.js
├── start-webview.js
├── start.js
├── utils
│ ├── build.js
│ ├── fox.js
│ ├── sketchtool.js
│ └── todos.js
└── webview
│ ├── build-bak.js
│ └── build.js
├── src
├── plugin
│ ├── index.js
│ ├── manifest.json
│ └── utils
│ │ ├── .gitkeep
│ │ ├── core.js
│ │ ├── debug
│ │ ├── debug.js
│ │ ├── index.js
│ │ └── window.js
│ │ ├── formatter.js
│ │ └── webview
│ │ ├── index.js
│ │ ├── webview.js
│ │ └── window.js
└── webview
│ ├── assets
│ ├── fonts
│ │ └── icomoon
│ │ │ ├── fonts
│ │ │ ├── icomoon.eot
│ │ │ ├── icomoon.svg
│ │ │ ├── icomoon.ttf
│ │ │ └── icomoon.woff
│ │ │ ├── selection.json
│ │ │ └── style.css
│ └── sketch-logo.svg
│ ├── index.html
│ ├── js
│ ├── components
│ │ ├── actions
│ │ │ ├── action-details.js
│ │ │ ├── action-timeline.js
│ │ │ └── action.js
│ │ ├── console
│ │ │ └── log-list.js
│ │ ├── elements
│ │ │ ├── element-tree-item.js
│ │ │ └── element-tree.js
│ │ ├── link.js
│ │ ├── log
│ │ │ ├── array.js
│ │ │ ├── class.js
│ │ │ ├── empty.js
│ │ │ ├── number.js
│ │ │ ├── object.js
│ │ │ ├── string.js
│ │ │ └── value.js
│ │ ├── network
│ │ │ ├── network-request-details.js
│ │ │ ├── network-request-timeline.js
│ │ │ └── network-request.js
│ │ └── screens
│ │ │ ├── 404.js
│ │ │ ├── actions.js
│ │ │ ├── app.js
│ │ │ ├── console.js
│ │ │ ├── elements.js
│ │ │ └── network.js
│ ├── data
│ │ ├── actions.js
│ │ ├── console.js
│ │ ├── elements.js
│ │ └── network.js
│ ├── index.js
│ ├── routes.js
│ ├── store.js
│ └── utils
│ │ ├── redux.js
│ │ └── sketch.js
│ └── scss
│ ├── _colors.scss
│ ├── _fonts.scss
│ ├── _shadows.scss
│ ├── actions.scss
│ ├── app.scss
│ ├── console.scss
│ ├── elements.scss
│ ├── filters.scss
│ ├── network.scss
│ ├── panel.scss
│ └── tabs.scss
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
3 | # Build folder
4 | Contents/
5 |
6 | # Parsed ObjC class headers
7 | headers/parsed/*.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Julian Burr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
5 | # Sketch Plugin Debugger
6 |
7 | **Please note this repo is still in the experimental stage, things may or may not be working and APIs will most likely change in the future**
8 |
9 | This tool was born out of the frustration of existing debugging tools for Sketch plugin development. It is a concept for a debugger console in form of an easily instalable Sketch plugin, as well as a bundle of util functions that can be pulled into any project using npm.
10 |
11 |
12 | ## Util functions
13 |
14 | ### Why?
15 |
16 | In the Sketch plugin development environment, the global `log` function is provided to create system logs (alias for [`NSLog`](https://developer.apple.com/reference/foundation/1395275-nslog?language=objc) I guess?!). But this function is not very flexible. It can only take one argument and it cannot divide into different log levels. So I decided create some small util functions, that behave more like the [`console`](https://developer.mozilla.org/en/docs/Web/API/console) functions I am used to from usual JS development...
17 |
18 | The util functions also send the logs to a seperate plugin, that can be installed if you wish so (it is not required! You are very welcome to keep using the System Console if you prefer so :)). For more infos, see [the plugin section](#plugin)
19 |
20 | ### Get started
21 |
22 | To import the debugger util functions, simply use npm:
23 | ```bash
24 | npm install --save sketch-debugger
25 |
26 | # Or yarn
27 | yarn add sketch-debugger
28 | ```
29 |
30 | Then import it wherever you need it...
31 |
32 | ```js
33 | import Debug from 'sketch-debugger';
34 | //...
35 | Debug.log('Hello', 'World', foo);
36 | Debug.warn('Some warning');
37 | Debug.error('This should not happen ;)');
38 | ```
39 |
40 | ### Methods
41 |
42 | The methods follow the same approach as the [console functions](https://developer.mozilla.org/en/docs/Web/API/console) JS developers are used to in the JS browser environment.
43 |
44 | **log(...args)**
45 | Default log method, takes any number of arguments and logs the passed value to the console (both the system log and the Sketch debugger plugin if available.
46 |
47 | **warn(...args)**
48 | Logs warnings (in the system console, the logs will have the leading `### WARN` and a trailing `#WARN END` log).
49 |
50 | **error(...args)**
51 | Logs errors (in the system console, the logs will have the leading `### ERROR` and a trailing `#ERROR END` log).
52 |
53 | **count(log)** *(work in progress)*
54 | Counts occurances of specified log (from last console.clear). In the system console, it adds the leading log `### COUNT: {count}`.
55 |
56 | **time(identifier)**/**timeEnd(identifier)** *(work in progress)*
57 | Creates a timer to measure time between two execution points. Creates the following logs in the system console: `### TIME START - {identifier}` / `### TIME END: {duration}ms - {identifier}`.
58 |
59 | **group(identifier)**/**groupEnd()** *(work in progress)*
60 | Creates a group and puts all following logs into this group until closed by groupEnd, which will always close the group that was opened last. This will add the following logs to the system console: `### GROUP START - {identifier}` / `### GROUP END - {identifier}`.
61 |
62 | **clear()** *(work in progress)*
63 | Clears the console memory. This will only affect the plugins console, not the system logs.
64 |
65 |
66 | ## Plugin
67 |
68 | ### Why?
69 |
70 | I use logs a lot during development. I grew up with Firebug and love the Chrome Debugger. And I hate the System Console :/ It is simply doesn't provide all the nice features I was used to from web development.
71 |
72 | So I decided to create a simple plugin with a GUI similar to those browser debuggers. Your logs can be classified (normal logs, warnings and erros), you can use other util functions like timers, groups and counters (*work in progress!*) and you have a lot of visual helpers to feel more comfortable during the debug process ;)
73 |
74 | ### Get started
75 |
76 | Download the `sketch-debugger.sketchplugin` file from this repo and double click (or manually move it into your Sketch plugin folder). That's it.
77 |
78 | Now you should have a new menu item under `Plugins` called `Open Debugger`. This will open a window with the debugger panels. Once this window is open, all logs (created by the sketch-debugger util functions) will be send to it! No further setup or anything else required :)
79 |
80 | ### Features
81 |
82 | **Console**
83 | Developers console with all the logs that have been created using the utils functions. Logs can be easily searched, filters, cleared, etc.
84 |
85 | *Work in progress:* It would nice to have a console functionality, where you can type in JS which will be executed on *Enter*, including that the selected log value gets copied into the namespace (e.g. as `$sel`), to be able e.g. to iterate through a logged collection...
86 |
87 | **Elements** *(work in progress)*
88 | This will give you a live representation of the Document / Page / Layer structure in your currently opened Sketch documents. Ideally at some point this will have an automated `MS*/NS*` documentation integrated showing all available methods on selected objects.
89 |
90 | **Actions** *(work in progress)*
91 | If possible I'd like to integrate a panel that show all actions, when they are triggered, what context they include, etc. Maybe also not limited to MSActions, but a general action observer.
92 |
93 | **Network** *(work in progress)*
94 | With a similar util library it would be possible to log network requests and responses, show timings, headers, parameters, etc.
95 |
96 |
97 |
98 |
99 |
100 | # Roadmap / Todos
101 |
102 | ## General
103 |
104 | - [x] ~~Pull bootstraped plugin out of [`sketch-plugin-boilerplate`](https://github.com/julianburr/sketch-plugin-boilerplate)~~
105 | - [x] ~~Create build structure that also creates compiled and optimized util folder to be used as npm entry point~~ *TODO: simplify (build) scripts*
106 | - [x] ~~Publish npm package~~
107 | - [ ] Create simple website with howtos and documentation of util functions
108 | - [ ] Debugger lib build
109 |
110 | ## Util Functions
111 | - [ ] .count method
112 | - [ ] .time* methods
113 | - [ ] .group* methods
114 |
115 | ## Plugin
116 | - [ ] Hook Sketch up to deliver data in specified format
117 | - [ ] Add stack trace now that I can get it with the preprocessor enabled + integrate [source map](https://github.com/mozilla/source-map) handling to show the original trace if plugin.js has a source map defined!
118 | - [x] ~~Finish console layout / design~~
119 | - [x] ~~Add element tree panel~~
120 | - [x] ~~Create HTTP request utils that also send data to debugger~~ see [`sketch-fetch`](https://github.com/julianburr/sketch-fetch)
121 | - [x] ~~Add network panel~~
122 | - [x] ~~Add actions panel~~
123 | - [ ] Add action listener (if possible without crashes :/) and add action panel
124 | - [ ] Integrate automated `MS*` documentation tool build on the [`class-dumps`](https://github.com/abynim/Sketch-Headers) if possible
125 | - [ ] Think about a way to read the system logs as well and turn them into a nicer/more readable format in the plugins console
126 |
--------------------------------------------------------------------------------
/config/plugin/babel.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | ['es2015', {
4 | modules: false
5 | }]
6 | ],
7 | 'plugins': [
8 | 'transform-object-rest-spread',
9 | ['module-resolver', {
10 | alias: {
11 | utils: './src/plugin/utils'
12 | }
13 | }]
14 | ]
15 | }
--------------------------------------------------------------------------------
/config/plugin/eslint.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['semistandard'],
3 | globals: {
4 | MSDocument: false,
5 | MSDocumentWindow: false,
6 | MSPage: false,
7 | MSSymbolInstance: false,
8 | MSSymbolMaster: false,
9 | MSTextLayer: false,
10 | NSAlert: false,
11 | NSApp: false,
12 | NSClassFromString: false,
13 | NSColor: false,
14 | NSData: false,
15 | NSDocument: false,
16 | NSDocumentController: false,
17 | NSFileManager: false,
18 | NSImage: false,
19 | NSJSONSerialization: false,
20 | NSMakeRect: false,
21 | NSMutableData: false,
22 | NSMutableURLRequest: false,
23 | NSSaveOperation: false,
24 | NSString: false,
25 | NSTextField: false,
26 | NSTextView: false,
27 | NSThread: false,
28 | NSTitledWindowMask: false,
29 | NSURL: false,
30 | NSURLRequest: false,
31 | NSUTF8StringEncoding: false,
32 | NSUserDefaults: false,
33 | NSView: false,
34 | NSViewHeightSizable: false,
35 | NSViewWidthSizable: false,
36 | NSWindow: false,
37 | NSWorkspace: false,
38 | WKWebView: false,
39 | WKWebViewConfiguration: false,
40 | Mocha: false,
41 | log: false,
42 | NSBackingStoreBuffered: false,
43 | NSPanel: false,
44 | NSResizableWindowMask: false,
45 | NSWindowStyleMaskClosable: false,
46 | SPBWebViewMessageHandler: false,
47 | SPBWebViewMessageUtils: false
48 | },
49 | parser: 'babel-eslint',
50 | plugins: [
51 | 'no-unused-vars-rest'
52 | ],
53 | rules: {
54 | eqeqeq: [
55 | 0
56 | ]
57 | }
58 | }
--------------------------------------------------------------------------------
/config/plugin/paths.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var fs = require('fs-extra');
3 |
4 | var appDirectory = fs.realpathSync(process.cwd());
5 | function resolveApp(relativePath) {
6 | return path.resolve(appDirectory, relativePath);
7 | }
8 |
9 | var src = resolveApp('src/plugin');
10 | var frameworks = resolveApp('src/frameworks');
11 |
12 | module.exports = {
13 | src,
14 | entry: resolveApp('src/plugin/index.js'),
15 | manifest: resolveApp('src/plugin/manifest.json'),
16 | build: resolveApp('Contents/Sketch'),
17 | bundle: resolveApp('sketch-plugin-boilerplate.sketchplugin'),
18 | frameworks,
19 | frameworksBuild: resolveApp('Contents/Resources/frameworks'),
20 | watch: [src, frameworks]
21 | };
22 |
--------------------------------------------------------------------------------
/config/plugin/webpack.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs-extra');
2 | var path = require('path');
3 | var chalk = require('chalk');
4 | var webpack = require('webpack');
5 | var objectAssign = require('object-assign');
6 |
7 | var paths = require('./paths');
8 | var babelConfig = require('./babel');
9 |
10 | var isDevelopment = process.env.NODE_ENV !== 'production';
11 |
12 | babelConfig = objectAssign(babelConfig, {
13 | cacheDirectory: isDevelopment,
14 | });
15 |
16 | module.exports = {
17 | entry: paths.entry,
18 | output: {
19 | path: paths.build,
20 | filename: 'plugin.js',
21 | library: 'handlers',
22 | libraryTarget: 'var'
23 | },
24 | module: {
25 | loaders: [
26 | {
27 | test: /\.(js|jsx)$/,
28 | include: paths.src,
29 | exclude: /(node_modules)/,
30 | use: {
31 | loader: 'babel-loader',
32 | options: babelConfig
33 | }
34 | }
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/config/webview/babel.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [ 'react-app' ],
3 | plugins: [
4 | 'transform-object-rest-spread',
5 | 'transform-decorators-legacy',
6 | [
7 | 'module-resolver',
8 | {
9 | alias: {
10 | webview: './src/webview',
11 | components: './src/webview/js/components',
12 | data: './src/webview/js/data',
13 | utils: './src/webview/js/utils',
14 | assets: './src/webview/assets',
15 | styles: './src/webview/scss'
16 | }
17 | }
18 | ]
19 | ],
20 | cacheDirectory: true
21 | };
22 |
--------------------------------------------------------------------------------
/config/webview/env.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const path = require('path');
3 | const paths = require('./paths');
4 |
5 | // Make sure that including paths.js after env.js will read .env variables.
6 | delete require.cache[require.resolve('./paths')];
7 |
8 | const NODE_ENV = process.env.NODE_ENV;
9 | if (!NODE_ENV) {
10 | throw new Error(
11 | 'The NODE_ENV environment variable is required but was not specified.'
12 | );
13 | }
14 |
15 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
16 | var dotenvFiles = [
17 | `${paths.dotenv}.${NODE_ENV}.local`,
18 | `${paths.dotenv}.${NODE_ENV}`,
19 | // Don't include `.env.local` for `test` environment
20 | // since normally you expect tests to produce the same
21 | // results for everyone
22 | NODE_ENV !== 'test' && `${paths.dotenv}.local`,
23 | paths.dotenv,
24 | ].filter(Boolean);
25 |
26 | // Load environment variables from .env* files. Suppress warnings using silent
27 | // if this file is missing. dotenv will never modify any environment variables
28 | // that have already been set.
29 | // https://github.com/motdotla/dotenv
30 | dotenvFiles.forEach(dotenvFile => {
31 | if (fs.existsSync(dotenvFile)) {
32 | require('dotenv').config({
33 | path: dotenvFile,
34 | });
35 | }
36 | });
37 |
38 | // We support resolving modules according to `NODE_PATH`.
39 | // This lets you use absolute paths in imports inside large monorepos:
40 | // https://github.com/facebookincubator/create-react-app/issues/253.
41 | // It works similar to `NODE_PATH` in Node itself:
42 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
43 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
44 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
45 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
46 | // We also resolve them to make sure all tools using them work consistently.
47 | const appDirectory = fs.realpathSync(process.cwd());
48 | process.env.NODE_PATH = (process.env.NODE_PATH || '')
49 | .split(path.delimiter)
50 | .filter(folder => folder && !path.isAbsolute(folder))
51 | .map(folder => path.resolve(appDirectory, folder))
52 | .join(path.delimiter);
53 |
54 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
55 | // injected into the application via DefinePlugin in Webpack configuration.
56 | const REACT_APP = /^REACT_APP_/i;
57 |
58 | function getClientEnvironment(publicUrl) {
59 | const raw = Object.keys(process.env)
60 | .filter(key => REACT_APP.test(key))
61 | .reduce(
62 | (env, key) => {
63 | env[key] = process.env[key];
64 | return env;
65 | },
66 | {
67 | // Useful for determining whether we’re running in production mode.
68 | // Most importantly, it switches React into the correct mode.
69 | NODE_ENV: process.env.NODE_ENV || 'development',
70 | // Useful for resolving the correct path to static assets in `public`.
71 | // For example, .
72 | // This should only be used as an escape hatch. Normally you would put
73 | // images into the `src` and `import` them in code to get their paths.
74 | PUBLIC_URL: publicUrl,
75 | }
76 | );
77 | // Stringify all values so we can feed into Webpack DefinePlugin
78 | const stringified = {
79 | 'process.env': Object.keys(raw).reduce((env, key) => {
80 | env[key] = JSON.stringify(raw[key]);
81 | return env;
82 | }, {}),
83 | };
84 |
85 | return { raw, stringified };
86 | }
87 |
88 | module.exports = getClientEnvironment;
--------------------------------------------------------------------------------
/config/webview/eslint.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: ['react'],
3 | extends: ['semistandard'],
4 | env: {
5 | es6: true
6 | },
7 | parser: 'babel-eslint',
8 | parserOptions: {
9 | sourceType: 'module',
10 | ecmaVersion: 6,
11 | ecmaFeatures: {
12 | impliedStrict: true,
13 | experimentalObjectRestSpread: true,
14 | jsx: true
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/config/webview/paths.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var fs = require('fs-extra');
3 |
4 | var appDirectory = fs.realpathSync(process.cwd());
5 | function resolveApp(relativePath) {
6 | return path.resolve(appDirectory, relativePath);
7 | }
8 |
9 | var nodePaths = (process.env.NODE_PATH || '')
10 | .split(process.platform === 'win32' ? ';' : ':')
11 | .filter(Boolean)
12 | .filter(folder => !path.isAbsolute(folder))
13 | .map(resolveApp);
14 |
15 | module.exports = {
16 | src: resolveApp('src/webview/'),
17 | build: resolveApp('Contents/Resources/webview/'),
18 | buildBundleJs: 'Contents/Resources/webview/js/index.js',
19 | indexHtml: resolveApp('src/webview/index.html'),
20 | indexJs: resolveApp('src/webview/js/index.js'),
21 | packageJson: resolveApp('package.json'),
22 | yarnLockFile: resolveApp('yarn.lock'),
23 | appNodeModules: resolveApp('node_modules'),
24 | ownNodeModules: resolveApp('node_modules'),
25 | nodePaths: nodePaths,
26 | yarnLockFile: resolveApp('yarn.lock'),
27 | homepage: './'
28 | };
--------------------------------------------------------------------------------
/config/webview/polyfills.js:
--------------------------------------------------------------------------------
1 | if (typeof Promise === 'undefined') {
2 | // Rejection tracking prevents a common issue where React gets into an
3 | // inconsistent state due to an error, but it gets swallowed by a Promise,
4 | // and the user has no idea what causes React's erratic future behavior.
5 | require('promise/lib/rejection-tracking').enable();
6 | window.Promise = require('promise/lib/es6-extensions.js');
7 | }
8 |
9 | // fetch() polyfill for making API calls.
10 | require('whatwg-fetch');
11 |
12 | // Object.assign() is commonly used with React.
13 | // It will use the native implementation if it's present and isn't buggy.
14 | Object.assign = require('object-assign');
15 |
--------------------------------------------------------------------------------
/config/webview/webpack-dev-server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const errorOverlayMiddleware = require('react-error-overlay/middleware');
4 | const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
5 | const config = require('./webpack-dev');
6 | const paths = require('./paths');
7 |
8 | const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
9 | const host = process.env.HOST || '0.0.0.0';
10 |
11 | module.exports = function(proxy, allowedHost) {
12 | return {
13 | // WebpackDevServer 2.4.3 introduced a security fix that prevents remote
14 | // websites from potentially accessing local content through DNS rebinding:
15 | // https://github.com/webpack/webpack-dev-server/issues/887
16 | // https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
17 | // However, it made several existing use cases such as development in cloud
18 | // environment or subdomains in development significantly more complicated:
19 | // https://github.com/facebookincubator/create-react-app/issues/2271
20 | // https://github.com/facebookincubator/create-react-app/issues/2233
21 | // While we're investigating better solutions, for now we will take a
22 | // compromise. Since our WDS configuration only serves files in the `public`
23 | // folder we won't consider accessing them a vulnerability. However, if you
24 | // use the `proxy` feature, it gets more dangerous because it can expose
25 | // remote code execution vulnerabilities in backends like Django and Rails.
26 | // So we will disable the host check normally, but enable it if you have
27 | // specified the `proxy` setting. Finally, we let you override it if you
28 | // really know what you're doing with a special environment variable.
29 | disableHostCheck:
30 | !proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
31 | // Enable gzip compression of generated files.
32 | compress: true,
33 | // Silence WebpackDevServer's own logs since they're generally not useful.
34 | // It will still show compile warnings and errors with this setting.
35 | clientLogLevel: 'none',
36 | // By default WebpackDevServer serves physical files from current directory
37 | // in addition to all the virtual build products that it serves from memory.
38 | // This is confusing because those files won’t automatically be available in
39 | // production build folder unless we copy them. However, copying the whole
40 | // project directory is dangerous because we may expose sensitive files.
41 | // Instead, we establish a convention that only files in `public` directory
42 | // get served. Our build script will copy `public` into the `build` folder.
43 | // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
44 | //
45 | // In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
46 | // Note that we only recommend to use `public` folder as an escape hatch
47 | // for files like `favicon.ico`, `manifest.json`, and libraries that are
48 | // for some reason broken when imported through Webpack. If you just want to
49 | // use an image, put it in `src` and `import` it from JavaScript instead.
50 | contentBase: paths.src,
51 | // By default files from `contentBase` will not trigger a page reload.
52 | watchContentBase: true,
53 | // Enable hot reloading server. It will provide /sockjs-node/ endpoint
54 | // for the WebpackDevServer client so it can learn when the files were
55 | // updated. The WebpackDevServer client is included as an entry point
56 | // in the Webpack development configuration. Note that only changes
57 | // to CSS are currently hot reloaded. JS changes will refresh the browser.
58 | hot: true,
59 | // It is important to tell WebpackDevServer to use the same "root" path
60 | // as we specified in the config. In development, we always serve from /.
61 | publicPath: config.build,
62 | // WebpackDevServer is noisy by default so we emit custom message instead
63 | // by listening to the compiler events with `compiler.plugin` calls above.
64 | quiet: true,
65 | // Reportedly, this avoids CPU overload on some systems.
66 | // https://github.com/facebookincubator/create-react-app/issues/293
67 | watchOptions: {
68 | ignored: /node_modules/,
69 | },
70 | // Enable HTTPS if the HTTPS environment variable is set to 'true'
71 | https: protocol === 'https',
72 | host: host,
73 | overlay: false,
74 | historyApiFallback: {
75 | // Paths with dots should still use the history fallback.
76 | // See https://github.com/facebookincubator/create-react-app/issues/387.
77 | disableDotRule: true,
78 | },
79 | public: allowedHost,
80 | proxy,
81 | setup(app) {
82 | // This lets us open files from the runtime error overlay.
83 | app.use(errorOverlayMiddleware());
84 | // This service worker file is effectively a 'no-op' that will reset any
85 | // previous service worker registered for the same host:port combination.
86 | // We do this in development to avoid hitting the production cache if
87 | // it used the same host and port.
88 | // https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
89 | app.use(noopServiceWorkerMiddleware());
90 | },
91 | };
92 | };
93 |
--------------------------------------------------------------------------------
/config/webview/webpack-dev.js:
--------------------------------------------------------------------------------
1 | const autoprefixer = require('autoprefixer');
2 | const path = require('path');
3 | const webpack = require('webpack');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
6 |
7 | const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
8 | const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
9 | const eslintFormatter = require('react-dev-utils/eslintFormatter');
10 | const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
11 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
12 |
13 | const getClientEnvironment = require('./env');
14 | const paths = require('./paths');
15 |
16 | // Webpack uses `publicPath` to determine where the app is being served from.
17 | // In development, we always serve from the root. This makes config easier.
18 | const publicPath = '/';
19 | // `publicUrl` is just like `publicPath`, but we will provide it to our app
20 | // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
21 | // Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz.
22 | const publicUrl = '';
23 | // Get environment variables to inject into our app.
24 | const env = getClientEnvironment(publicUrl);
25 |
26 | const cssLoader = {
27 | loader: require.resolve('css-loader'),
28 | options: {
29 | importLoaders: 1,
30 | }
31 | };
32 | const babel = require('./babel');
33 |
34 | const postCssLoader = {
35 | loader: require.resolve('postcss-loader'),
36 | options: {
37 | // Necessary for external CSS imports to work
38 | // https://github.com/facebookincubator/create-react-app/issues/2677
39 | ident: 'postcss',
40 | plugins: () => [
41 | require('postcss-flexbugs-fixes'),
42 | autoprefixer({
43 | browsers: [
44 | '>1%',
45 | 'last 4 versions',
46 | 'Firefox ESR',
47 | 'not ie < 9', // React doesn't support IE8 anyway
48 | ],
49 | flexbox: 'no-2009',
50 | }),
51 | ],
52 | },
53 | };
54 |
55 | // This is the development configuration.
56 | // It is focused on developer experience and fast rebuilds.
57 | // The production configuration is different and lives in a separate file.
58 |
59 |
60 | module.exports = {
61 | // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
62 | // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
63 | devtool: 'cheap-module-source-map',
64 | // These are the "entry points" to our application.
65 | // This means they will be the "root" imports that are included in JS bundle.
66 | // The first two entry points enable "hot" CSS and auto-refreshes for JS.
67 | entry: [
68 | // Include an alternative client for WebpackDevServer. A client's job is to
69 | // connect to WebpackDevServer by a socket and get notified about changes.
70 | // When you save a file, the client will either apply hot updates (in case
71 | // of CSS changes), or refresh the page (in case of JS changes). When you
72 | // make a syntax error, this client will display a syntax error overlay.
73 | // Note: instead of the default WebpackDevServer client, we use a custom one
74 | // to bring better experience for Create React App users. You can replace
75 | // the line below with these two lines if you prefer the stock client:
76 | // require.resolve('webpack-dev-server/client') + '?/',
77 | // require.resolve('webpack/hot/dev-server'),
78 | require.resolve('react-dev-utils/webpackHotDevClient'),
79 | // We ship a few polyfills by default:
80 | require.resolve('./polyfills'),
81 | // Errors should be considered fatal in development
82 | require.resolve('react-error-overlay'),
83 | // Finally, this is your app's code:
84 | paths.indexJs,
85 | // We include the app code last so that if there is a runtime error during
86 | // initialization, it doesn't blow up the WebpackDevServer client, and
87 | // changing JS code would still trigger a refresh.
88 | ],
89 | output: {
90 | // Next line is not used in dev but WebpackDevServer crashes without it:
91 | path: paths.build,
92 | // Add /* filename */ comments to generated require()s in the output.
93 | pathinfo: true,
94 | // This does not produce a real file. It's just the virtual path that is
95 | // served by WebpackDevServer in development. This is the JS bundle
96 | // containing code from all our entry points, and the Webpack runtime.
97 | filename: 'static/js/bundle.js',
98 | // There are also additional JS chunk files if you use code splitting.
99 | chunkFilename: 'static/js/[name].chunk.js',
100 | // This is the URL that app is served from. We use "/" in development.
101 | publicPath: publicPath,
102 | // Point sourcemap entries to original disk location (format as URL on Windows)
103 | devtoolModuleFilenameTemplate: info =>
104 | path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
105 | },
106 | resolve: {
107 | // This allows you to set a fallback for where Webpack should look for modules.
108 | // We placed these paths second because we want `node_modules` to "win"
109 | // if there are any conflicts. This matches Node resolution mechanism.
110 | // https://github.com/facebookincubator/create-react-app/issues/253
111 | modules: ['node_modules', paths.appNodeModules].concat(
112 | // It is guaranteed to exist because we tweak it in `env.js`
113 | process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
114 | ),
115 | // These are the reasonable defaults supported by the Node ecosystem.
116 | // We also include JSX as a common component filename extension to support
117 | // some tools, although we do not recommend using it, see:
118 | // https://github.com/facebookincubator/create-react-app/issues/290
119 | // `web` extension prefixes have been added for better support
120 | // for React Native Web.
121 | extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx'],
122 | alias: {
123 |
124 | // Support React Native Web
125 | // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
126 | 'react-native': 'react-native-web',
127 | },
128 | plugins: [
129 | // Prevents users from importing files from outside of src/ (or node_modules/).
130 | // This often causes confusion because we only process files within src/ with babel.
131 | // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
132 | // please link the files into your node_modules/ and let module-resolution kick in.
133 | // Make sure your source files are compiled, as they will not be processed in any way.
134 | new ModuleScopePlugin(paths.src),
135 | ],
136 | },
137 | module: {
138 | strictExportPresence: true,
139 | rules: [
140 | // ** ADDING/UPDATING LOADERS **
141 | // The "file" loader handles all assets unless explicitly excluded.
142 | // The `exclude` list *must* be updated with every change to loader extensions.
143 | // When adding a new loader, you must add its `test`
144 | // as a new entry in the `exclude` list for "file" loader.
145 |
146 | // "file" loader makes sure those assets get served by WebpackDevServer.
147 | // When you `import` an asset, you get its (virtual) filename.
148 | // In production, they would get copied to the `build` folder.
149 | {
150 | exclude: [
151 | /\.html$/,
152 | /\.(js|jsx)$/,
153 | /\.css$/,
154 | /\.json$/,
155 | /\.bmp$/,
156 | /\.gif$/,
157 | /\.jpe?g$/,
158 | /\.png$/,
159 | ],
160 | loader: require.resolve('file-loader'),
161 | options: {
162 | name: 'static/media/[name].[hash:8].[ext]',
163 | },
164 | },
165 | // "url" loader works like "file" loader except that it embeds assets
166 | // smaller than specified limit in bytes as data URLs to avoid requests.
167 | // A missing `test` is equivalent to a match.
168 | {
169 | test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
170 | loader: require.resolve('url-loader'),
171 | options: {
172 | limit: 10000,
173 | name: 'static/media/[name].[hash:8].[ext]',
174 | },
175 | },
176 | // Process JS with Babel.
177 | {
178 | test: /\.(js|jsx)$/,
179 | include: paths.src,
180 | loader: require.resolve('babel-loader'),
181 | options: babel
182 | },
183 |
184 | // "postcss" loader applies autoprefixer to our CSS.
185 | // "css" loader resolves paths in CSS and adds assets as dependencies.
186 | {
187 | test: /\.scss$/,
188 | loader: ExtractTextPlugin.extract(
189 | Object.assign(
190 | {
191 | fallback: require.resolve('style-loader'),
192 | use: [
193 | cssLoader,
194 | {
195 | loader: require.resolve('sass-loader')
196 | },
197 | postCssLoader
198 | ]
199 | },
200 | {}
201 | )
202 | ),
203 | },
204 |
205 | // "postcss" loader applies autoprefixer to our CSS.
206 | // "css" loader resolves paths in CSS and adds assets as dependencies.
207 | {
208 | test: /\.css$/,
209 | use: [
210 | require.resolve('style-loader'),
211 | cssLoader,
212 | postCssLoader
213 | ],
214 | },
215 | // ** STOP ** Are you adding a new loader?
216 | // Remember to add the new extension(s) to the "file" loader exclusion list.
217 | ],
218 | },
219 | plugins: [
220 | // Makes some environment variables available in index.html.
221 | // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
222 | //
223 | // In development, this will be an empty string.
224 | new InterpolateHtmlPlugin(env.raw),
225 | // Generates an `index.html` file with the