webpack.config.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. const defaultsDeep = require('lodash.defaultsdeep');
  2. var path = require('path');
  3. var webpack = require('webpack');
  4. // Plugins
  5. var CopyWebpackPlugin = require('copy-webpack-plugin');
  6. var HtmlWebpackPlugin = require('html-webpack-plugin');
  7. var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  8. // PostCss
  9. var autoprefixer = require('autoprefixer');
  10. var postcssVars = require('postcss-simple-vars');
  11. var postcssImport = require('postcss-import');
  12. const STATIC_PATH = process.env.STATIC_PATH || '/static';
  13. const base = {
  14. mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
  15. devtool: 'cheap-module-source-map',
  16. devServer: {
  17. contentBase: path.resolve(__dirname, 'build'),
  18. host: 'localhost',
  19. port: process.env.PORT || 8080
  20. },
  21. output: {
  22. library: 'GUI',
  23. filename: '[name].js',
  24. chunkFilename: 'chunks/[name].js'
  25. },
  26. externals: {
  27. React: 'react',
  28. ReactDOM: 'react-dom'
  29. },
  30. resolve: {
  31. symlinks: false
  32. },
  33. module: {
  34. rules: [{
  35. test: /\.jsx?$/,
  36. loader: 'babel-loader',
  37. include: [
  38. path.resolve(__dirname, 'src'),
  39. /node_modules[\\/]scratch-[^\\/]+[\\/]src/,
  40. /node_modules[\\/]pify/,
  41. /node_modules[\\/]@vernier[\\/]godirect/
  42. ],
  43. options: {
  44. // Explicitly disable babelrc so we don't catch various config
  45. // in much lower dependencies.
  46. babelrc: false,
  47. plugins: [
  48. '@babel/plugin-syntax-dynamic-import',
  49. '@babel/plugin-transform-async-to-generator',
  50. '@babel/plugin-proposal-object-rest-spread',
  51. ['react-intl', {
  52. messagesDir: './translations/messages/'
  53. }]],
  54. presets: ['@babel/preset-env', '@babel/preset-react']
  55. }
  56. },
  57. {
  58. test: /\.css$/,
  59. use: [{
  60. loader: 'style-loader'
  61. }, {
  62. loader: 'css-loader',
  63. options: {
  64. modules: true,
  65. importLoaders: 1,
  66. localIdentName: '[name]_[local]_[hash:base64:5]',
  67. camelCase: true
  68. }
  69. }, {
  70. loader: 'postcss-loader',
  71. options: {
  72. ident: 'postcss',
  73. plugins: function () {
  74. return [
  75. postcssImport,
  76. postcssVars,
  77. autoprefixer
  78. ];
  79. }
  80. }
  81. }]
  82. }]
  83. },
  84. optimization: {
  85. minimizer: [
  86. new UglifyJsPlugin({
  87. include: /\.min\.js$/
  88. })
  89. ]
  90. },
  91. plugins: []
  92. };
  93. module.exports = [
  94. // to run editor examples
  95. defaultsDeep({}, base, {
  96. entry: {
  97. 'lib.min': ['react', 'react-dom'],
  98. 'gui': './src/playground/index.jsx',
  99. 'blocksonly': './src/playground/blocks-only.jsx',
  100. 'compatibilitytesting': './src/playground/compatibility-testing.jsx',
  101. 'player': './src/playground/player.jsx'
  102. },
  103. output: {
  104. path: path.resolve(__dirname, 'build'),
  105. filename: '[name].js'
  106. },
  107. externals: {
  108. React: 'react',
  109. ReactDOM: 'react-dom'
  110. },
  111. module: {
  112. rules: base.module.rules.concat([
  113. {
  114. test: /\.(svg|png|wav|gif|jpg)$/,
  115. loader: 'file-loader',
  116. options: {
  117. outputPath: 'static/assets/'
  118. }
  119. }
  120. ])
  121. },
  122. optimization: {
  123. splitChunks: {
  124. chunks: 'all',
  125. name: 'lib.min'
  126. },
  127. runtimeChunk: {
  128. name: 'lib.min'
  129. }
  130. },
  131. plugins: base.plugins.concat([
  132. new webpack.DefinePlugin({
  133. 'process.env.NODE_ENV': '"' + process.env.NODE_ENV + '"',
  134. 'process.env.DEBUG': Boolean(process.env.DEBUG),
  135. 'process.env.GA_ID': '"' + (process.env.GA_ID || 'UA-000000-01') + '"'
  136. }),
  137. new HtmlWebpackPlugin({
  138. chunks: ['lib.min', 'gui'],
  139. template: 'src/playground/index.ejs',
  140. title: '科乐维·少儿编程 - 停课不停学,免费公益编程课',
  141. sentryConfig: process.env.SENTRY_CONFIG ? '"' + process.env.SENTRY_CONFIG + '"' : null
  142. }),
  143. new HtmlWebpackPlugin({
  144. chunks: ['lib.min', 'blocksonly'],
  145. template: 'src/playground/index.ejs',
  146. filename: 'blocks-only.html',
  147. title: 'Scratch 3.0 GUI: Blocks Only Example'
  148. }),
  149. new HtmlWebpackPlugin({
  150. chunks: ['lib.min', 'compatibilitytesting'],
  151. template: 'src/playground/index.ejs',
  152. filename: 'compatibility-testing.html',
  153. title: 'Scratch 3.0 GUI: Compatibility Testing'
  154. }),
  155. new HtmlWebpackPlugin({
  156. chunks: ['lib.min', 'player'],
  157. template: 'src/playground/index.ejs',
  158. filename: 'player.html',
  159. title: 'Scratch 3.0 GUI: Player Example'
  160. }),
  161. new CopyWebpackPlugin([{
  162. from: 'static',
  163. to: 'static'
  164. }]),
  165. new CopyWebpackPlugin([{
  166. from: 'node_modules/scratch-blocks/media',
  167. to: 'static/blocks-media'
  168. }]),
  169. new CopyWebpackPlugin([{
  170. from: 'extensions/**',
  171. to: 'static',
  172. context: 'src/examples'
  173. }]),
  174. new CopyWebpackPlugin([{
  175. from: 'extension-worker.{js,js.map}',
  176. context: 'node_modules/scratch-vm/dist/web'
  177. }])
  178. ])
  179. })
  180. ].concat(
  181. process.env.NODE_ENV === 'production' || process.env.BUILD_MODE === 'dist' ? (
  182. // export as library
  183. defaultsDeep({}, base, {
  184. target: 'web',
  185. entry: {
  186. 'scratch-gui': './src/index.js'
  187. },
  188. output: {
  189. libraryTarget: 'umd',
  190. path: path.resolve('dist'),
  191. publicPath: `${STATIC_PATH}/`
  192. },
  193. externals: {
  194. React: 'react',
  195. ReactDOM: 'react-dom'
  196. },
  197. module: {
  198. rules: base.module.rules.concat([
  199. {
  200. test: /\.(svg|png|wav|gif|jpg)$/,
  201. loader: 'file-loader',
  202. options: {
  203. outputPath: 'static/assets/',
  204. publicPath: `${STATIC_PATH}/assets/`
  205. }
  206. }
  207. ])
  208. },
  209. plugins: base.plugins.concat([
  210. new CopyWebpackPlugin([{
  211. from: 'node_modules/scratch-blocks/media',
  212. to: 'static/blocks-media'
  213. }]),
  214. new CopyWebpackPlugin([{
  215. from: 'extension-worker.{js,js.map}',
  216. context: 'node_modules/scratch-vm/dist/web'
  217. }]),
  218. // Include library JSON files for scratch-desktop to use for downloading
  219. new CopyWebpackPlugin([{
  220. from: 'src/lib/libraries/*.json',
  221. to: 'libraries',
  222. flatten: true
  223. }])
  224. ])
  225. })) : []
  226. );