@@ -4,6 +4,9 @@ const paths = require('./paths');
44const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ;
55const CaseSensitivePathsPlugin = require ( 'case-sensitive-paths-webpack-plugin' ) ;
66const childProcess = require ( 'child_process' ) ;
7+ const SWPrecacheWebpackPlugin = require ( 'sw-precache-webpack-plugin' ) ;
8+ const CopyWebpackPlugin = require ( 'copy-webpack-plugin' ) ;
9+ const HappyPack = require ( 'happypack' ) ;
710const WatchMissingNodeModulesPlugin = require ( '../scripts/utils/WatchMissingNodeModulesPlugin' ) ;
811const env = require ( './env' ) ;
912
@@ -24,21 +27,25 @@ const COMMIT_HASH = childProcess
2427 . toString ( ) ;
2528const VERSION = `${ COMMIT_COUNT } -${ COMMIT_HASH } ` ;
2629
30+ const publicPath = __PROD__
31+ ? 'https://codesandbox.io/'
32+ : 'https://codesandbox.dev/' ;
33+
2734const getOutput = ( ) =>
2835 __DEV__
2936 ? {
3037 path : paths . appBuild ,
3138 pathinfo : true ,
3239 filename : 'static/js/[name].js' ,
33- publicPath : '/' ,
40+ publicPath,
3441 }
3542 : {
3643 path : paths . appBuild ,
3744 pathinfo : true ,
3845 filename : 'static/js/[name].[chunkhash].js' ,
3946 chunkFilename : 'static/js/[name].[chunkhash].chunk.js' ,
4047 sourceMapFilename : '[file].map' , // Default
41- publicPath : 'https://codesandbox.io/' ,
48+ publicPath,
4249 } ;
4350
4451const config = {
@@ -55,7 +62,7 @@ const config = {
5562 require . resolve ( './polyfills' ) ,
5663 path . join ( paths . embedSrc , 'index.js' ) ,
5764 ] ,
58- vendor : [ 'codemirror' , ' react', 'react-dom' , 'styled-components' ] ,
65+ vendor : [ 'react' , 'react-dom' , 'styled-components' , 'babel-standalone '] ,
5966 } ,
6067
6168 target : 'web' ,
@@ -73,24 +80,8 @@ const config = {
7380 {
7481 test : / \. j s $ / ,
7582 include : paths . src ,
76- exclude : [ / e s l i n t \. j s $ / ] ,
77- loader : 'babel-loader' ,
78- options : babelConfig ,
79- } ,
80- // Used to remove strict mode from eval:
81- {
82- test : / e v a l \/ j s \. j s $ / ,
83- include : paths . src ,
84- loader : 'babel-loader?cacheDirectory' ,
85- options : ( ( ) => {
86- const altererdConfig = Object . assign ( { } , babelConfig ) ;
87-
88- // prettier-ignore
89- altererdConfig . plugins . push (
90- require . resolve ( 'babel-plugin-transform-remove-strict-mode' )
91- ) ;
92- return altererdConfig ;
93- } ) ( ) ,
83+ exclude : [ / e s l i n t \. 4 \. 1 \. 0 \. m i n \. j s $ / , / t y p e s c r i p t S e r v i c e s \. j s $ / ] ,
84+ loader : 'happypack/loader' ,
9485 } ,
9586 // JSON is not enabled by default in Webpack but both Node and Browserify
9687 // allow it implicitly so we also enable it.
@@ -152,6 +143,8 @@ const config = {
152143 } ,
153144 } ,
154145 ] ,
146+
147+ noParse : [ / e s l i n t \. 4 \. 1 \. 0 \. m i n \. j s $ / , / t y p e s c r i p t S e r v i c e s \. j s $ / ] ,
155148 } ,
156149
157150 resolve : {
@@ -166,6 +159,14 @@ const config = {
166159 } ,
167160
168161 plugins : [
162+ new HappyPack ( {
163+ loaders : [
164+ {
165+ path : 'babel-loader' ,
166+ query : babelConfig ,
167+ } ,
168+ ] ,
169+ } ) ,
169170 // Generates an `index.html` file with the <script> injected.
170171 new HtmlWebpackPlugin ( {
171172 inject : true ,
@@ -234,6 +235,19 @@ const config = {
234235 // makes the discovery automatic so you don't have to restart.
235236 // See https://github.com/facebookincubator/create-react-app/issues/186
236237 new WatchMissingNodeModulesPlugin ( paths . appNodeModules ) ,
238+ // Make the monaco editor work
239+ new CopyWebpackPlugin ( [
240+ {
241+ from : __DEV__
242+ ? 'node_modules/monaco-editor/dev/vs'
243+ : 'node_modules/monaco-editor/min/vs' ,
244+ to : 'public/vs' ,
245+ } ,
246+ {
247+ from : 'src/homepage/static' ,
248+ to : 'static' ,
249+ } ,
250+ ] ) ,
237251 // Try to dedupe duplicated modules, if any:
238252 new webpack . optimize . CommonsChunkPlugin ( {
239253 name : 'common' ,
@@ -246,7 +260,7 @@ const config = {
246260 new webpack . optimize . CommonsChunkPlugin ( {
247261 async : true ,
248262 children : true ,
249- minChunks : 4 ,
263+ minChunks : 2 ,
250264 } ) ,
251265 new webpack . NamedModulesPlugin ( ) ,
252266 ] ,
@@ -290,6 +304,165 @@ if (__PROD__) {
290304 } ,
291305 sourceMap : true ,
292306 } ) ,
307+ // Generate a service worker script that will precache, and keep up to date,
308+ // the HTML & assets that are part of the Webpack build.
309+ new SWPrecacheWebpackPlugin ( {
310+ // By default, a cache-busting query parameter is appended to requests
311+ // used to populate the caches, to ensure the responses are fresh.
312+ // If a URL is already hashed by Webpack, then there is no concern
313+ // about it being stale, and the cache-busting can be skipped.
314+ dontCacheBustUrlsMatching : / \. \w { 8 } \. / ,
315+ filename : 'service-worker.js' ,
316+ cacheId : 'code-sandbox' ,
317+ logger ( message ) {
318+ if ( message . indexOf ( 'Total precache size is' ) === 0 ) {
319+ // This message occurs for every build and is a bit too noisy.
320+ return ;
321+ }
322+ if ( message . indexOf ( 'Skipping static resource' ) === 0 ) {
323+ // This message obscures real errors so we ignore it.
324+ // https://github.com/facebookincubator/create-react-app/issues/2612
325+ return ;
326+ }
327+ console . log ( message ) ;
328+ } ,
329+ minify : true ,
330+ // For unknown URLs, fallback to the index page
331+ navigateFallback : publicPath + 'app.html' ,
332+ // Ignores URLs starting from /__ (useful for Firebase):
333+ // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
334+ navigateFallbackWhitelist : [ / ^ (? ! \/ _ _ ) .* / ] ,
335+ // Don't precache sourcemaps (they're large) and build asset manifest:
336+ staticFileGlobsIgnorePatterns : [ / \. m a p $ / , / a s s e t - m a n i f e s t \. j s o n $ / ] ,
337+ maximumFileSizeToCacheInBytes : 5242880 ,
338+ runtimeCaching : [
339+ {
340+ urlPattern : / a p i \/ v 1 \/ s a n d b o x e s / ,
341+ handler : 'networkFirst' ,
342+ options : {
343+ cache : {
344+ maxEntries : 50 ,
345+ name : 'sandboxes-cache' ,
346+ } ,
347+ } ,
348+ } ,
349+ {
350+ urlPattern : / ^ h t t p s : \/ \/ u n p k g \. c o m / ,
351+ handler : 'cacheFirst' ,
352+ options : {
353+ cache : {
354+ maxEntries : 300 ,
355+ name : 'unpkg-cache' ,
356+ } ,
357+ } ,
358+ } ,
359+ {
360+ urlPattern : / c l o u d f l a r e \. c o m / ,
361+ handler : 'cacheFirst' ,
362+ options : {
363+ cache : {
364+ maxEntries : 20 ,
365+ name : 'cloudflare-cache' ,
366+ } ,
367+ } ,
368+ } ,
369+ ] ,
370+ } ) ,
371+ // Generate a service worker script that will precache, and keep up to date,
372+ // the HTML & assets that are part of the Webpack build.
373+ new SWPrecacheWebpackPlugin ( {
374+ // By default, a cache-busting query parameter is appended to requests
375+ // used to populate the caches, to ensure the responses are fresh.
376+ // If a URL is already hashed by Webpack, then there is no concern
377+ // about it being stale, and the cache-busting can be skipped.
378+ dontCacheBustUrlsMatching : / \. \w { 8 } \. / ,
379+ filename : 'sandbox-service-worker.js' ,
380+ logger ( message ) {
381+ if ( message . indexOf ( 'Total precache size is' ) === 0 ) {
382+ // This message occurs for every build and is a bit too noisy.
383+ return ;
384+ }
385+ if ( message . indexOf ( 'Skipping static resource' ) === 0 ) {
386+ // This message obscures real errors so we ignore it.
387+ // https://github.com/facebookincubator/create-react-app/issues/2612
388+ return ;
389+ }
390+ console . log ( message ) ;
391+ } ,
392+ minify : true ,
393+ // For unknown URLs, fallback to the index page
394+ navigateFallback : 'https://new.codesandbox.io/frame.html' ,
395+ staticFileGlobs : [ 'www/frame.html' ] ,
396+ stripPrefix : 'www/' ,
397+ cacheId : 'code-sandbox-sandbox' ,
398+ // Ignores URLs starting from /__ (useful for Firebase):
399+ // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
400+ navigateFallbackWhitelist : [ / ^ (? ! \/ _ _ ) .* / ] ,
401+ // Don't precache sourcemaps (they're large) and build asset manifest:
402+ staticFileGlobsIgnorePatterns : [ / \. m a p $ / , / a s s e t - m a n i f e s t \. j s o n $ / ] ,
403+ maximumFileSizeToCacheInBytes : 10485760 ,
404+ runtimeCaching : [
405+ {
406+ urlPattern : / a p i \/ v 1 \/ s a n d b o x e s / ,
407+ handler : 'networkFirst' ,
408+ options : {
409+ cache : {
410+ maxEntries : 50 ,
411+ name : 'sandboxes-cache' ,
412+ } ,
413+ } ,
414+ } ,
415+ {
416+ // These should be dynamic, since it's not loaded from this domain
417+ // But from the root domain
418+ urlPattern : / c o d e s a n d b o x \. i o \/ s t a t i c \/ j s \/ ( v e n d o r | c o m m o n | s a n d b o x ) / ,
419+ handler : 'networkFirst' ,
420+ options : {
421+ cache : {
422+ name : 'static-root-cache' ,
423+ } ,
424+ } ,
425+ } ,
426+ {
427+ urlPattern : / a p i \/ v 1 \/ s a n d b o x e s / ,
428+ handler : 'networkFirst' ,
429+ options : {
430+ cache : {
431+ maxEntries : 50 ,
432+ name : 'sandboxes-cache' ,
433+ } ,
434+ } ,
435+ } ,
436+ {
437+ urlPattern : / \. a m a z o n a w s \. c o m \/ p r o d \/ p a c k a g e / ,
438+ handler : 'fastest' ,
439+ options : {
440+ cache : {
441+ // a week
442+ maxAgeSeconds : 60 * 60 * 24 * 7 ,
443+ name : 'dependency-url-generator-cache' ,
444+ } ,
445+ } ,
446+ } ,
447+ {
448+ urlPattern : / h t t p s : \/ \/ d 3 i 2 v 4 d x q v x a q 9 \. c l o u d f r o n t \. n e t / ,
449+ handler : 'fastest' ,
450+ options : {
451+ cache : {
452+ maxEntries : 200 ,
453+ name : 'dependency-files-cache' ,
454+ } ,
455+ } ,
456+ } ,
457+ ] ,
458+ } ) ,
459+ // Moment.js is an extremely popular library that bundles large locale files
460+ // by default due to how Webpack interprets its code. This is a practical
461+ // solution that requires the user to opt into importing specific locales.
462+ // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
463+ // You can remove this if you don't use Moment.js:
464+ new webpack . IgnorePlugin ( / ^ \. \/ l o c a l e $ / , / m o m e n t $ / ) ,
465+ new webpack . optimize . ModuleConcatenationPlugin ( ) ,
293466 ] ;
294467} else {
295468 config . plugins = [
0 commit comments