webpacker 6.0.0.beta.2 → 6.0.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -18
  3. data/Gemfile.lock +1 -1
  4. data/README.md +96 -219
  5. data/docs/assets.md +135 -0
  6. data/docs/cloud9.md +310 -0
  7. data/docs/css.md +303 -0
  8. data/docs/deployment.md +148 -0
  9. data/docs/docker.md +68 -0
  10. data/docs/engines.md +213 -0
  11. data/docs/env.md +68 -0
  12. data/docs/es6.md +72 -0
  13. data/docs/folder-structure.md +66 -0
  14. data/docs/integrations.md +220 -0
  15. data/docs/misc.md +23 -0
  16. data/docs/props.md +187 -0
  17. data/docs/react.md +183 -0
  18. data/docs/target.md +22 -0
  19. data/docs/testing.md +147 -0
  20. data/docs/troubleshooting.md +158 -0
  21. data/docs/typescript.md +190 -0
  22. data/docs/v4-upgrade.md +142 -0
  23. data/docs/webpack-dev-server.md +94 -0
  24. data/docs/webpack.md +315 -0
  25. data/docs/yarn.md +23 -0
  26. data/lib/install/examples/vue3/app.vue +27 -0
  27. data/lib/install/examples/vue3/hello_vue.js +15 -0
  28. data/lib/install/javascript/packs/application.js +1 -3
  29. data/lib/webpacker/compiler.rb +2 -8
  30. data/lib/webpacker/version.rb +1 -1
  31. data/package.json +1 -1
  32. data/package/babel/preset-react.js +62 -0
  33. data/package/babel/preset.js +13 -24
  34. data/package/environments/__tests__/base.js +1 -1
  35. data/package/environments/base.js +19 -19
  36. data/package/environments/production.js +30 -28
  37. data/package/index.js +2 -7
  38. data/package/rules/coffee.js +5 -5
  39. data/package/rules/erb.js +3 -5
  40. data/package/rules/file.js +3 -5
  41. data/package/rules/index.js +17 -9
  42. data/package/rules/less.js +10 -14
  43. data/package/rules/sass.js +9 -13
  44. data/package/rules/svg.js +23 -0
  45. data/package/utils/get_style_rule.js +31 -27
  46. data/package/utils/helpers.js +0 -23
  47. metadata +29 -7
  48. data/6_0_upgrade.md +0 -43
  49. data/package/rules/raw.js +0 -5
  50. data/package/rules/stylus.js +0 -26
@@ -0,0 +1,23 @@
1
+ # Yarn
2
+
3
+ Webpacker by default uses `yarn` as a package manager for `node_modules`
4
+
5
+
6
+ ## Add a new npm module
7
+
8
+ To add any new JS module you can use `yarn`:
9
+
10
+ ```bash
11
+ yarn add bootstrap material-ui
12
+ ```
13
+
14
+ ## Add an npm module to `devDependencies`
15
+ To add a new JS module that will only be available to local development:
16
+
17
+ ```bash
18
+ yarn add --dev browser-sync
19
+ ```
20
+
21
+ Be careful not to add any build or app related JS modules in this fashion. Adding JS modules to `devDependencies` [will block them from being installed in **any** production environment](https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-production-true-false).
22
+
23
+ Docs from JS modules may instruct you to use `--dev` or `devDependencies`, but this is generally under the assumption that you are using a `node.js` workflow.
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <p>
3
+ {{ message }}
4
+ </p>
5
+ </template>
6
+
7
+ <script>
8
+ import { ref } from 'vue'
9
+
10
+ export default {
11
+ name: 'HelloWorld',
12
+ setup() {
13
+ const message = ref('Hello World')
14
+
15
+ return {
16
+ message
17
+ }
18
+ }
19
+ }
20
+ </script>
21
+
22
+ <style scoped>
23
+ p {
24
+ font-size: 2em;
25
+ text-align: center;
26
+ }
27
+ </style>
@@ -0,0 +1,15 @@
1
+ /* eslint no-console: 0 */
2
+ // Run this example by adding <%= javascript_pack_tag 'hello_vue' %> (and
3
+ // <%= stylesheet_pack_tag 'hello_vue' %> if you have styles in your component)
4
+ // to the head of your layout file,
5
+ // like app/views/layouts/application.html.erb.
6
+ // Create a div container with the id 'vue-app' <div id='vue-app'></div>
7
+ // It renders <p>Hello Vue</p> into it.
8
+
9
+ import { createApp } from "vue";
10
+ import App from "../app.vue";
11
+
12
+ document.addEventListener("DOMContentLoaded", () => {
13
+ const app = createApp(App);
14
+ app.mount("#vue-app");
15
+ });
@@ -7,6 +7,7 @@
7
7
  // To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
8
8
  // layout file, like app/views/layouts/application.html.erb
9
9
 
10
+
10
11
  // Uncomment to copy all static images under ../images to the output folder and reference
11
12
  // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
12
13
  // or the `imagePath` JavaScript helper below.
@@ -14,7 +15,4 @@
14
15
  // const images = require.context('../images', true)
15
16
  // const imagePath = (name) => images(name, true)
16
17
 
17
- import 'core-js/stable'
18
- import 'regenerator-runtime/runtime'
19
-
20
18
  console.log('Hello World from Webpacker')
@@ -28,7 +28,7 @@ class Webpacker::Compiler
28
28
  record_compilation_digest
29
29
  end
30
30
  else
31
- logger.debug "Everything's up-to-date. Nothing to do"
31
+ logger.info "Everything's up-to-date. Nothing to do"
32
32
  true
33
33
  end
34
34
  end
@@ -65,18 +65,12 @@ class Webpacker::Compiler
65
65
  compilation_digest_path.write(watched_files_digest)
66
66
  end
67
67
 
68
- def optionalRubyRunner
69
- bin_webpack_path = config.root_path.join("bin/webpack")
70
- first_line = File.readlines(bin_webpack_path).first.chomp
71
- /ruby/.match?(first_line) ? RbConfig.ruby : ""
72
- end
73
-
74
68
  def run_webpack
75
69
  logger.info "Compiling..."
76
70
 
77
71
  stdout, stderr, status = Open3.capture3(
78
72
  webpack_env,
79
- "#{optionalRubyRunner} ./bin/webpack",
73
+ "#{RbConfig.ruby} ./bin/webpack",
80
74
  chdir: File.expand_path(config.root_path)
81
75
  )
82
76
 
@@ -1,4 +1,4 @@
1
1
  module Webpacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "6.0.0.beta.2".freeze
3
+ VERSION = "6.0.0.pre.1".freeze
4
4
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rails/webpacker",
3
- "version": "6.0.0-beta.2",
3
+ "version": "6.0.0-pre.1",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "main": "package/index.js",
6
6
  "files": [
@@ -0,0 +1,62 @@
1
+ module.exports = function config(api) {
2
+ const validEnv = ['development', 'test', 'production']
3
+ const currentEnv = api.env()
4
+ const isDevelopmentEnv = api.env('development')
5
+ const isProductionEnv = api.env('production')
6
+ const isTestEnv = api.env('test')
7
+
8
+ if (!validEnv.includes(currentEnv)) {
9
+ throw new Error(
10
+ `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(currentEnv)}".`
11
+ )
12
+ }
13
+
14
+ return {
15
+ presets: [
16
+ isTestEnv && [
17
+ '@babel/preset-env',
18
+ {
19
+ targets: { node: 'current' },
20
+ modules: 'commonjs'
21
+ }
22
+ ],
23
+ (isProductionEnv || isDevelopmentEnv) && [
24
+ '@babel/preset-env',
25
+ {
26
+ useBuiltIns: 'entry',
27
+ corejs: '3.8',
28
+ modules: false,
29
+ bugfixes: true,
30
+ loose: true,
31
+ exclude: ['transform-typeof-symbol']
32
+ }
33
+ ],
34
+ [
35
+ '@babel/preset-react',
36
+ {
37
+ development: isDevelopmentEnv || isTestEnv,
38
+ useBuiltIns: true
39
+ }
40
+ ]
41
+ ].filter(Boolean),
42
+ plugins: [
43
+ 'babel-plugin-macros',
44
+ [
45
+ '@babel/plugin-proposal-class-properties',
46
+ { loose: true }
47
+ ],
48
+ [
49
+ '@babel/plugin-transform-runtime',
50
+ {
51
+ helpers: false,
52
+ regenerator: true,
53
+ corejs: false
54
+ }
55
+ ],
56
+ isProductionEnv && [
57
+ 'babel-plugin-transform-react-remove-prop-types',
58
+ { removeImport: true }
59
+ ]
60
+ ].filter(Boolean)
61
+ }
62
+ }
@@ -1,5 +1,3 @@
1
- const { moduleExists } = require('@rails/webpacker')
2
-
3
1
  module.exports = function config(api) {
4
2
  const validEnv = ['development', 'test', 'production']
5
3
  const currentEnv = api.env()
@@ -9,15 +7,16 @@ module.exports = function config(api) {
9
7
 
10
8
  if (!validEnv.includes(currentEnv)) {
11
9
  throw new Error(
12
- `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(
13
- currentEnv
14
- )}".`
10
+ `Please specify a valid NODE_ENV or BABEL_ENV environment variable. Valid values are "development", "test", and "production". Instead, received: "${JSON.stringify(currentEnv)}".`
15
11
  )
16
12
  }
17
13
 
18
14
  return {
19
15
  presets: [
20
- isTestEnv && ['@babel/preset-env', { targets: { node: 'current' } }],
16
+ isTestEnv && [
17
+ '@babel/preset-env',
18
+ { targets: { node: 'current' } }
19
+ ],
21
20
  (isProductionEnv || isDevelopmentEnv) && [
22
21
  '@babel/preset-env',
23
22
  {
@@ -28,28 +27,18 @@ module.exports = function config(api) {
28
27
  loose: true,
29
28
  exclude: ['transform-typeof-symbol']
30
29
  }
31
- ],
32
- moduleExists('@babel/preset-typescript') && [
33
- '@babel/preset-typescript',
34
- { allExtensions: true, isTSX: true }
35
- ],
36
- moduleExists('@babel/preset-react') && [
37
- '@babel/preset-react',
38
- {
39
- development: isDevelopmentEnv || isTestEnv,
40
- useBuiltIns: true
41
- }
42
30
  ]
43
31
  ].filter(Boolean),
44
32
  plugins: [
45
33
  'babel-plugin-macros',
46
- ['@babel/plugin-proposal-class-properties', { loose: true }],
47
- ['@babel/plugin-transform-runtime', { helpers: false }],
48
- isProductionEnv &&
49
- moduleExists('babel-plugin-transform-react-remove-prop-types') && [
50
- 'babel-plugin-transform-react-remove-prop-types',
51
- { removeImport: true }
52
- ]
34
+ [
35
+ '@babel/plugin-proposal-class-properties',
36
+ { loose: true }
37
+ ],
38
+ [
39
+ '@babel/plugin-transform-runtime',
40
+ { helpers: false }
41
+ ]
53
42
  ].filter(Boolean)
54
43
  }
55
44
  }
@@ -44,7 +44,7 @@ describe('Base config', () => {
44
44
  })
45
45
 
46
46
  test('should return default plugins', () => {
47
- expect(baseConfig.plugins.length).toEqual(3)
47
+ expect(baseConfig.plugins.length).toEqual(4)
48
48
  })
49
49
 
50
50
  test('should return default resolveLoader', () => {
@@ -4,20 +4,19 @@
4
4
  const { basename, dirname, join, relative, resolve } = require('path')
5
5
  const extname = require('path-complete-extname')
6
6
  const PnpWebpackPlugin = require('pnp-webpack-plugin')
7
- const { sync: globSync } = require('glob')
7
+ const { sync } = require('glob')
8
8
  const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
9
9
  const WebpackAssetsManifest = require('webpack-assets-manifest')
10
10
  const webpack = require('webpack')
11
11
  const rules = require('../rules')
12
12
  const config = require('../config')
13
13
  const { isDevelopment } = require('../env')
14
- const { moduleExists } = require('../utils/helpers')
15
14
 
16
15
  const getEntryObject = () => {
17
16
  const entries = {}
18
17
  const rootPath = join(config.source_path, config.source_entry_path)
19
18
 
20
- globSync(`${rootPath}/**/*.*`).forEach((path) => {
19
+ sync(`${rootPath}/**/*.*`).forEach((path) => {
21
20
  const namespace = relative(join(rootPath), dirname(path))
22
21
  const name = join(namespace, basename(path, extname(path)))
23
22
  let assetPaths = resolve(path)
@@ -53,6 +52,7 @@ const getModulePaths = () => {
53
52
  const getPlugins = () => {
54
53
  const plugins = [
55
54
  new webpack.EnvironmentPlugin(process.env),
55
+ PnpWebpackPlugin,
56
56
  new CaseSensitivePathsPlugin(),
57
57
  new WebpackAssetsManifest({
58
58
  entrypoints: true,
@@ -63,18 +63,18 @@ const getPlugins = () => {
63
63
  })
64
64
  ]
65
65
 
66
- if (moduleExists('css-loader') && moduleExists('mini-css-extract-plugin')) {
67
- const MiniCssExtractPlugin = require('mini-css-extract-plugin')
68
- plugins.push(
69
- new MiniCssExtractPlugin({
70
- filename: isDevelopment
71
- ? 'css/[name].css'
72
- : 'css/[name]-[contenthash:8].css',
73
- chunkFilename: isDevelopment
74
- ? 'css/[id].css'
75
- : 'css/[id]-[contenthash:8].css'
76
- })
77
- )
66
+ try {
67
+ if (require.resolve('css-loader')) {
68
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
69
+ plugins.push(
70
+ new MiniCssExtractPlugin({
71
+ filename: isDevelopment ? '[name].css' : '[name].[contenthash:8].css',
72
+ chunkFilename: isDevelopment ? '[id].css' : '[id].[contenthash:8].css'
73
+ })
74
+ )
75
+ }
76
+ } catch (e) {
77
+ /* Work out what to print here */
78
78
  }
79
79
 
80
80
  return plugins
@@ -86,14 +86,14 @@ module.exports = {
86
86
  filename: 'js/[name]-[contenthash].js',
87
87
  chunkFilename: 'js/[name]-[contenthash].chunk.js',
88
88
  hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
89
+ assetModuleFilename: 'static/[hash][ext][query]',
89
90
  path: config.outputPath,
90
91
  publicPath: config.publicPath
91
92
  },
92
93
  entry: getEntryObject(),
93
94
  resolve: {
94
- extensions: ['.js', '.mjs', '.ts', '.coffee'],
95
- modules: getModulePaths(),
96
- plugins: [PnpWebpackPlugin]
95
+ extensions: ['.js', '.mjs', '.ts'],
96
+ modules: getModulePaths()
97
97
  },
98
98
 
99
99
  plugins: getPlugins(),
@@ -106,7 +106,7 @@ module.exports = {
106
106
  optimization: {
107
107
  splitChunks: { chunks: 'all' },
108
108
 
109
- runtimeChunk: 'single'
109
+ runtimeChunk: { name: (entrypoint) => `runtime-${entrypoint.name}` }
110
110
  },
111
111
 
112
112
  module: {
@@ -5,42 +5,45 @@ const { merge } = require('webpack-merge')
5
5
  const CompressionPlugin = require('compression-webpack-plugin')
6
6
  const TerserPlugin = require('terser-webpack-plugin')
7
7
  const baseConfig = require('./base')
8
- const { moduleExists } = require('../utils/helpers')
9
8
 
10
9
  const getPlugins = () => {
11
- const plugins = []
10
+ let compressionPlugin = new CompressionPlugin({
11
+ filename: '[path].gz[query]',
12
+ algorithm: 'gzip',
13
+ test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
14
+ })
12
15
 
13
- plugins.push(
14
- new CompressionPlugin({
15
- filename: '[path][base].gz[query]',
16
- algorithm: 'gzip',
16
+ if ('brotli' in process.versions) {
17
+ compressionPlugin = new CompressionPlugin({
18
+ filename: '[path].br[query]',
19
+ algorithm: 'brotliCompress',
17
20
  test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
18
21
  })
19
- )
20
-
21
- if ('brotli' in process.versions) {
22
- plugins.push(
23
- new CompressionPlugin({
24
- filename: '[path][base].br[query]',
25
- algorithm: 'brotliCompress',
26
- test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/
27
- })
28
- )
29
22
  }
30
23
 
31
- return plugins
32
- }
24
+ const plugins = [compressionPlugin]
33
25
 
34
- const tryCssMinimizer = () => {
35
- if (
36
- moduleExists('css-loader') &&
37
- moduleExists('css-minimizer-webpack-plugin')
38
- ) {
39
- const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
40
- return new CssMinimizerPlugin({ sourceMap: true })
26
+ try {
27
+ if (require.resolve('css-loader')) {
28
+ const OptimizeCSSAssetsPlugin = require.resolve(
29
+ 'optimize-css-assets-webpack-plugin'
30
+ )
31
+ const safePostCssParser = require.resolve('postcss-safe-parser')
32
+ plugins.push(
33
+ new OptimizeCSSAssetsPlugin({
34
+ parser: safePostCssParser,
35
+ map: {
36
+ inline: false,
37
+ annotation: true
38
+ }
39
+ })
40
+ )
41
+ }
42
+ } catch (e) {
43
+ /* Work out what to output without clutter */
41
44
  }
42
45
 
43
- return null
46
+ return plugins
44
47
  }
45
48
 
46
49
  const productionConfig = {
@@ -50,7 +53,6 @@ const productionConfig = {
50
53
  plugins: getPlugins(),
51
54
  optimization: {
52
55
  minimizer: [
53
- tryCssMinimizer(),
54
56
  new TerserPlugin({
55
57
  parallel: Number.parseInt(process.env.WEBPACKER_PARALLEL, 10) || true,
56
58
  terserOptions: {
@@ -72,7 +74,7 @@ const productionConfig = {
72
74
  }
73
75
  }
74
76
  })
75
- ].filter(Boolean)
77
+ ]
76
78
  }
77
79
  }
78
80
 
@@ -1,15 +1,13 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
- const { merge } = require('webpack-merge')
5
4
  const { resolve } = require('path')
6
5
  const { existsSync } = require('fs')
7
6
  const baseConfig = require('./environments/base')
8
- const rules = require('./rules')
7
+ const loaders = require('./rules')
9
8
  const config = require('./config')
10
9
  const devServer = require('./dev_server')
11
10
  const { nodeEnv } = require('./env')
12
- const { moduleExists, canProcess } = require('./utils/helpers')
13
11
 
14
12
  const webpackConfig = () => {
15
13
  const path = resolve(__dirname, 'environments', `${nodeEnv}.js`)
@@ -22,8 +20,5 @@ module.exports = {
22
20
  devServer,
23
21
  webpackConfig: webpackConfig(),
24
22
  baseConfig,
25
- rules,
26
- merge,
27
- moduleExists,
28
- canProcess
23
+ loaders
29
24
  }