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

Sign up to get free protection for your applications and to get access to all the features.
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
  }